【发布时间】:2022-01-16 13:12:23
【问题描述】:
在我的数据框中,我有多个包含学生成绩的列。我想总结“测验”列(例如,Quiz1、Quiz2)。但是,我只想总结前 2 个值,而忽略其他值。我想用总数(即前 2 个值的总和)创建一个新列。还有一个问题是成绩与给定行中的前 2 个成绩并列。例如,Aaron 的最高分是 42,但有两个分数并列第二高(即 36)。
数据
df <-
structure(
list(
Student = c("Aaron", "James", "Charlotte", "Katie", "Olivia",
"Timothy", "Grant", "Chloe", "Judy", "Justin"),
ID = c(30016, 87311, 61755, 55323, 94839, 38209, 34096,
98432, 19487, 94029),
Quiz1 = c(31, 25, 41, 10, 35, 19, 27, 42, 15, 20),
Quiz2 = c(42, 33, 34, 22, 23, 38, 48, 49, 23, 30),
Quiz3 = c(36, 36, 34, 32, 43, 38, 44, 42, 42, 37),
Quiz4 = c(36, 43, 39, 46, 40, 38, 43, 35, 41, 41)
),
row.names = c(NA, -10L),
class = c("tbl_df", "tbl", "data.frame")
)
我知道我可以使用pivot_longer 来做到这一点,这样我就可以按组排列,然后为每个学生取前 2 个值。这很好用,但我觉得tidyverse 应该有一种更有效的方法,而不是来回转动。
我尝试过的
df %>%
tidyr::pivot_longer(-c(Student, ID)) %>%
dplyr::group_by(Student, ID) %>%
dplyr::arrange(desc(value), .by_group = TRUE) %>%
dplyr::slice_head(n = 2) %>%
tidyr::pivot_wider(names_from = name, values_from = value) %>%
dplyr::ungroup() %>%
dplyr::mutate(Total = rowSums(select(., starts_with("Quiz")), na.rm = TRUE))
我也知道,如果我想对每一行的所有列求和,那么我可以使用rowSums,就像我在上面使用的那样。但是,我不确定如何对 4 个测验列中的前 2 个值执行 rowSums。
预期输出
# A tibble: 10 × 7
Student ID Quiz2 Quiz3 Quiz1 Quiz4 Total
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Aaron 30016 42 36 NA NA 78
2 Charlotte 61755 NA NA 41 39 80
3 Chloe 98432 49 NA 42 NA 91
4 Grant 34096 48 44 NA NA 92
5 James 87311 NA 36 NA 43 79
6 Judy 19487 NA 42 NA 41 83
7 Justin 94029 NA 37 NA 41 78
8 Katie 55323 NA 32 NA 46 78
9 Olivia 94839 NA 43 NA 40 83
10 Timothy 38209 38 38 NA NA 76
【问题讨论】:
-
如果您对
collapse没意见,那么ftransform(gvr(df, "Student|ID"), dapply(gvr(df, "^Quiz"), MARGIN = 1, FUN = function(x) replace(x, radixorder(radixorder(x)) %in% 1:2, NA))) %>% ftransform(Total = rowSums(gvr(., "^Quiz"), na.rm = TRUE))是一个快速的逐行选项