首页 > 解决方案 > 如何构建表格以捕获更改

问题描述

我有一个小 df,其中包含多个测试中两个班级的分数。我想建立一个表格来展示从第一次测试到每次测试的变化。

df 看起来像这样:

在此处输入图像描述

我要构建的新表如下所示:

在此处输入图像描述

因此,我们可以为每个测试知道有多少学生在哪个年级以及他们的第一次测试结果。我应该怎么做才能建立这样的表?我是否必须构建每一行然后将它们绑定在一起?有什么聪明的办法吗?

样本数据:

df<-structure(list(Class = c("A", "A", "A", "A", "A", "A", "A", "B", 
"B", "B", "B", "B", "B", "B", "B"), Student = c("Mike", "Mike", 
"Mike", "Mike", "John", "John", "John", "Rose", "Rose", "Rose", 
"Rose", "Linda", "Linda", "Linda", "Linda"), Test = c(1, 2, 3, 
4, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4), Score = c("A", "B", "B", 
"A", "C", "B", "A", "D", "B", "C", "D", "D", "C", "B", "B")), row.names = c(NA, 
-15L), class = c("tbl_df", "tbl", "data.frame"))

标签: r

解决方案


唷,那是一个艰难的过程。不确定是否有更简单的选择,但考虑到不同的聚合/分组级别以及以下事实:a)并非所有所需的输出行都是数据的一部分,b)您的学生都没有得分“B”第一次测试,很难得到更短的代码版本。

注意:对于“B”类,测试 3,您的预期输出显示测试 1 = D 和测试结果 = A/B 的结果。但是,您的数据显示 Rose 从 D 到 C,Linda 从 D 到 B,所以我想这是一个错误。

df %>%
  group_by(Class, Student) %>%
  mutate(first_result = Score[Test == 1],
         first_result = fct_expand(first_result, LETTERS[1:4])) %>%
  ungroup() %>%
  complete(Class, Test, Score, first_result) %>%
  mutate(first_result = as.character(first_result)) %>%
  group_by(Class, Test) %>%
  mutate(student_per_test = length(unique(Student[!is.na(Student)])),
         result = if_else(!is.na(Student), 1L, NA_integer_)) %>%
  filter(Test != 1) %>%
  select(-Student) %>%
  ungroup() %>%
  arrange(Class, Test, Score, first_result) %>%
  pivot_wider(names_from = first_result,
              values_from = result)

这使:

# A tibble: 24 x 8
   Class  Test Score student_per_test     A     B     C     D
   <chr> <dbl> <chr>            <int> <int> <int> <int> <int>
 1 A         2 A                    2    NA    NA    NA    NA
 2 A         2 B                    2     1    NA     1    NA
 3 A         2 C                    2    NA    NA    NA    NA
 4 A         2 D                    2    NA    NA    NA    NA
 5 A         3 A                    2    NA    NA     1    NA
 6 A         3 B                    2     1    NA    NA    NA
 7 A         3 C                    2    NA    NA    NA    NA
 8 A         3 D                    2    NA    NA    NA    NA
 9 A         4 A                    1     1    NA    NA    NA
10 A         4 B                    1    NA    NA    NA    NA
11 A         4 C                    1    NA    NA    NA    NA
12 A         4 D                    1    NA    NA    NA    NA
13 B         2 A                    2    NA    NA    NA    NA
14 B         2 B                    2    NA    NA    NA     1
15 B         2 C                    2    NA    NA    NA     1
16 B         2 D                    2    NA    NA    NA    NA
17 B         3 A                    2    NA    NA    NA    NA
18 B         3 B                    2    NA    NA    NA     1
19 B         3 C                    2    NA    NA    NA     1
20 B         3 D                    2    NA    NA    NA    NA
21 B         4 A                    2    NA    NA    NA    NA
22 B         4 B                    2    NA    NA    NA     1
23 B         4 C                    2    NA    NA    NA    NA
24 B         4 D                    2    NA    NA    NA     1

请注意,空单元格是NA.

如果需要,您可以在上面的代码末尾添加另一行代码,将这些列转换为空字符串:

mutate(across(LETTERS[1:4], ~replace_na(.x, "")))

但是,这会将数字列转换为字符列。如果你愿意,这取决于你。

在此处输入图像描述


推荐阅读