如何按组计算所有列的平均值?

13

我需要用R计算一个大型数据集的所有列的平均值,按照两个变量进行分组。

让我们用mtcars测试一下:

library(dplyr)
g_mtcars <- group_by(mtcars, cyl, gear)
summarise(g_mtcars, mean (hp))

# Source: local data frame [8 x 3]
# Groups: cyl [?]
# 
#     cyl  gear `mean(hp)`
#   <dbl> <dbl>      <dbl>
# 1     4     3    97.0000
# 2     4     4    76.0000
# 3     4     5   102.0000
# 4     6     3   107.5000
# 5     6     4   116.5000
# 6     6     5   175.0000
# 7     8     3   194.1667
# 8     8     5   299.5000

它适用于"hp",但我需要获取mtcars的每一列(除了“cyl”和“gear”组成的组)的平均值。数据集很大,有几列。手动输入,例如: summarise(g_mtcars, mean(hp), mean(drat), mean(wt),...) 不切实际。


请使用任何你想要的 R 函数。PS:使用summarize只是我的第一次尝试。 - Miguel Rozsas
1
我们应该猜测哪个包含group_by函数的包?请确保示例是可重现的。 - Bhas
@Bhas 不是的,我们不是。这个函数来自 dplyr 包,这应该在帖子中提到。我已经编辑了它。 - RHertel
7个回答

30

编辑2:最近版本的dplyr建议使用带有across函数的常规summarise,例如:

library(dplyr)
mtcars %>% 
group_by(cyl, gear) %>%
summarise(across(everything(), mean))

你需要的是从 dplyr 中使用 ?summarise_all 或者 ?summarise_each

编辑:完整代码:

library(dplyr)
mtcars %>% 
    group_by(cyl, gear) %>%
    summarise_all("mean")

# Source: local data frame [8 x 11]
# Groups: cyl [?]
# 
#     cyl  gear    mpg     disp       hp     drat       wt    qsec    vs    am     carb
#   <dbl> <dbl>  <dbl>    <dbl>    <dbl>    <dbl>    <dbl>   <dbl> <dbl> <dbl>    <dbl>
# 1     4     3 21.500 120.1000  97.0000 3.700000 2.465000 20.0100   1.0  0.00 1.000000
# 2     4     4 26.925 102.6250  76.0000 4.110000 2.378125 19.6125   1.0  0.75 1.500000
# 3     4     5 28.200 107.7000 102.0000 4.100000 1.826500 16.8000   0.5  1.00 2.000000
# 4     6     3 19.750 241.5000 107.5000 2.920000 3.337500 19.8300   1.0  0.00 1.000000
# 5     6     4 19.750 163.8000 116.5000 3.910000 3.093750 17.6700   0.5  0.50 4.000000
# 6     6     5 19.700 145.0000 175.0000 3.620000 2.770000 15.5000   0.0  1.00 6.000000
# 7     8     3 15.050 357.6167 194.1667 3.120833 4.104083 17.1425   0.0  0.00 3.083333
# 8     8     5 15.400 326.0000 299.5000 3.880000 3.370000 14.5500   0.0  1.00 6.000000

太好了!我不知道summarise_all(和summarise_each)这些函数,这对我来说是新的。非常感谢! - Miguel Rozsas
在您的原始答案和“Edit2”中,您将如何将na.rm = TRUE参数输入到mean函数中? - Dylan Dijk
你可以传递一个 purrr 风格的 lambda 作为函数,例如 ~ mean(., na.rm = TRUE)),而不仅仅是函数名。 - Wojciech Książek

6

aggregate是在base中实现这一目的最简单的方法:

aggregate(. ~ cyl + gear, data = mtcars, FUN = mean)
#   cyl gear    mpg     disp       hp     drat       wt    qsec  vs   am     carb
# 1   4    3 21.500 120.1000  97.0000 3.700000 2.465000 20.0100 1.0 0.00 1.000000
# 2   6    3 19.750 241.5000 107.5000 2.920000 3.337500 19.8300 1.0 0.00 1.000000
# 3   8    3 15.050 357.6167 194.1667 3.120833 4.104083 17.1425 0.0 0.00 3.083333
# 4   4    4 26.925 102.6250  76.0000 4.110000 2.378125 19.6125 1.0 0.75 1.500000
# 5   6    4 19.750 163.8000 116.5000 3.910000 3.093750 17.6700 0.5 0.50 4.000000
# 6   4    5 28.200 107.7000 102.0000 4.100000 1.826500 16.8000 0.5 1.00 2.000000
# 7   6    5 19.700 145.0000 175.0000 3.620000 2.770000 15.5000 0.0 1.00 6.000000
# 8   8    5 15.400 326.0000 299.5000 3.880000 3.370000 14.5500 0.0 1.00 6.000000

4

使用data.table库。(但是不能使用setDT(mtcars),因为绑定是锁定的。请将其复制到另一个名称,例如dt,并进行尝试。

 library(data.table)
 mt_dt = as.data.table(mtcars)
 mt_dt[ , lapply(.SD, mean) , by=c("cyl", "gear")]

谢谢!这对我有用。我会学习更多关于setDT的知识,因为这是新的东西。 - Miguel Rozsas
基本上,setDT有助于将data.frame转换为data.table。 - joel.wilson
非常干净和简单的解决方案,但是在我的情况下有很多列是因子。gmean(somefactorcolumname)中的错误:对于因子,平均值没有意义。使用mt_dt[ , lapply(.SD, mean) , by=c("cyl", "gear"), .SDcols = sapply(mt_dt, is.numeric) ]可以保证安全。 - Birte

0

使用 dplyr 1.1.0,您可以使用 .by 进行内联分组:

summarise(mtcars, across(everything(), mean), .by = c(cyl, gear))

#   cyl gear    mpg     disp       hp     drat       wt    qsec  vs   am     carb
# 1   6    4 19.750 163.8000 116.5000 3.910000 3.093750 17.6700 0.5 0.50 4.000000
# 2   4    4 26.925 102.6250  76.0000 4.110000 2.378125 19.6125 1.0 0.75 1.500000
# 3   6    3 19.750 241.5000 107.5000 2.920000 3.337500 19.8300 1.0 0.00 1.000000
# 4   8    3 15.050 357.6167 194.1667 3.120833 4.104083 17.1425 0.0 0.00 3.083333
# 5   4    3 21.500 120.1000  97.0000 3.700000 2.465000 20.0100 1.0 0.00 1.000000
# 6   4    5 28.200 107.7000 102.0000 4.100000 1.826500 16.8000 0.5 1.00 2.000000
# 7   8    5 15.400 326.0000 299.5000 3.880000 3.370000 14.5500 0.0 1.00 6.000000
# 8   6    5 19.700 145.0000 175.0000 3.620000 2.770000 15.5000 0.0 1.00 6.000000

0

另一种可能性是使用collapse,这种方法明显更快:

library(collapse)
mtcars %>% 
  fgroup_by(cyl, gear) %>% 
  fmean()

#or, equivalently, fmean(mtcars, GRP(mtcars, ~ cyl + gear))

基准测试: collapse 更快。
microbenchmark::microbenchmark(
  collapse = mtcars %>% 
    fgroup_by(cyl, gear) %>% 
    fmean(),
  dplyr = summarise(mtcars, across(everything(), mean), .by = c(cyl, gear)),
  data.table = {mt_dt = as.data.table(mtcars)
  mt_dt[ , lapply(.SD, mean) , by=c("cyl", "gear")]},
  aggregate = aggregate(. ~ cyl + gear, data = mtcars, FUN = mean)
)

# Unit: microseconds
#        expr      min        lq     mean   median       uq       max neval
#    collapse   77.002  136.9505  150.770  152.051  168.401   311.001   100
#       dplyr 5588.001 6008.5515 6461.616 6257.501 6537.651 15146.801   100
#  data.table 3600.201 4404.0005 5284.708 5451.701 5784.752 12903.301   100
#   aggregate 2318.900 2581.5010 2812.408 2669.851 2778.851 10259.802   100

-1

为了完整起见,您可以使用plyr包来执行此操作:

library(plyr)
ddply(mtcars,c('cyl','gear'), summarize,mean_hp=mean(hp))

1
但是我仍然有同样的问题。如何获取大型数据集中每个变量的平均值。 - Miguel Rozsas
这回答解决了相关FAQ如何按组计算平均值,但它忽略了这个问题中的“所有列”。 - Gregor Thomas

-2
你可以在 dplyr::summarize 中使用多个 mean 语句,像这样:
library(dplyr)

mtcars %>% 
  group_by(cyl, gear) %>% 
  summarize(mean_hp = mean(hp), mean_wt = mean(wt))

# Source: local data frame [8 x 4]
# Groups: cyl [?]

#     cyl  gear  mean_hp  mean_wt
#   <dbl> <dbl>    <dbl>    <dbl>
# 1     4     3  97.0000 2.465000
# 2     4     4  76.0000 2.378125
# 3     4     5 102.0000 1.826500
# 4     6     3 107.5000 3.337500
# 5     6     4 116.5000 3.093750
# 6     6     5 175.0000 2.770000
# 7     8     3 194.1667 4.104083
# 8     8     5 299.5000 3.370000

这里我们需要猜测哪个包定义了 %>%?请确保示例是完全可重现的。 - Bhas
2
是的,我知道我可以这样做,但数据集很大,有太多列需要逐一输入。谢谢。 - Miguel Rozsas
1
引用问题,"像这样手动输入:summarise(g_mtcars, mean (hp), mean(drat), mean (wt),...) 是不切实际的。" - Gregor Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接