使用 dplyr 在保留其他变量的同时聚合数据框

Aggregate a data frame while keeping other variables, with dplyr

假设我有以下数据框(注意'score'的长度):

id = 1:10^8
school = LETTERS[1:10]
class = paste0(school, rep(1:10, each=10))
score = rnorm(10^8)

df = data.frame(id, school, class, score,
                stringsAsFactors = FALSE) 

我想计算这 100 个 类 中每一个的平均值。然而,我也想要 保持学校变量的结果。使用 dplyr:

df %>% group_by(class) %>% 
  summarise(mean = mean(score),
            school = unique(school))

这行得通,但速度很慢(在我的机器上需要 8 秒,而我的数据实际上要大得多)。我认为一种选择可能不是使用 unique(),而是使用 join() 家族的成员。但我需要先定义另一个 df 如下:

df_join = data.frame(class, school,
                     stringsAsFactors = FALSE)

然后:

df %>% group_by(class) %>% 
    summarise(mean = mean(score)) %>% 
    left_join(df_join)

这行得通并且速度不那么慢,因为现在需要 6 秒。然而,在这里创建 df_join 很容易,因为我发明了数据框,但在现实生活中,获得 df_join 可能更具挑战性。所以我只想使用原始数据框(df)。

有什么想法可以让 dplyr 更容易(也许更快)吗? (我在那里查了一下,但没有找到解决方案:Aggregate by factor levels, keeping other variables in the resulting data frame

由于每个 class 只有一所独特的学校,您可以简单地将学校变量包含在分组变量中:

df %>% group_by(school, class) %>% summarize(mean_score = mean(score))
# # A tibble: 100 x 3
# # Groups:   school [?]
# school class mean_score
# <chr>  <chr>      <dbl>
# 1 A      A1      0.000506
# 2 A      A10    -0.000275
# 3 A      A2      0.00136 
# 4 A      A3      0.000405
# 5 A      A4     -0.00156 
# 6 A      A5     -0.00214 
# 7 A      A6     -0.00108 
# 8 A      A7     -0.000534
# 9 A      A8      0.000804
# 10 A      A9      0.00106 
# # ... with 90 more rows

这是一个 data.table 等价物:

library(data.table)
setDT(df, key = c("school", "class"))
df[, .(mean_score = mean(score)), by=.(school, class)]