使用dplyr汇总多个列?

使用dplyr汇总多个列?,r,dplyr,aggregate,R,Dplyr,Aggregate,我对dplyr语法有点纠结。我有一个包含不同变量和一个分组变量的数据框。现在我想用R中的dplyr计算每组中每列的平均值 df <- data.frame( a = sample(1:5, n, replace = TRUE), b = sample(1:5, n, replace = TRUE), c = sample(1:5, n, replace = TRUE), d = sample(1:5, n, replace = TRUE),

我对dplyr语法有点纠结。我有一个包含不同变量和一个分组变量的数据框。现在我想用R中的dplyr计算每组中每列的平均值

df <- data.frame(
    a = sample(1:5, n, replace = TRUE), 
    b = sample(1:5, n, replace = TRUE), 
    c = sample(1:5, n, replace = TRUE), 
    d = sample(1:5, n, replace = TRUE), 
    grp = sample(1:3, n, replace = TRUE)
)
df %>% group_by(grp) %>% summarise(mean(a))

您只需将更多参数传递给
摘要

df %>% group_by(grp) %>% summarise(mean(a), mean(b), mean(c), mean(d))
来源:本地数据帧[3 x 5]

  grp  mean(a)  mean(b)  mean(c) mean(d)
1   1 2.500000 3.500000 2.000000     3.0
2   2 3.800000 3.200000 3.200000     2.8
3   3 3.666667 3.333333 2.333333     3.0
dplyr
(>=1.00)中,您可以使用
summary
中的
cross(everything()
将函数应用于所有变量:

库(dplyr)
df%>%分组依据(grp)%>%总结(跨越(所有内容(),列表(平均值)))
#>#tibble:3 x 5
#>grp a b c d
#>       
#> 1     1  3.08  2.98  2.98  2.91
#> 2     2  3.03  3.04  2.97  2.87
#> 3     3  2.85  2.95  2.95  3.06
或者,
purrlyr
包提供相同的功能:

库(purrryr)
df%%>%切片行(“grp”)%%>%dmap(平均值)
#>#tibble:3 x 5
#>grp a b c d
#>       
#> 1     1  3.08  2.98  2.98  2.91
#> 2     2  3.03  3.04  2.97  2.87
#> 3     3  2.85  2.95  2.95  3.06
也不要忘记
数据表
(使用
keyby
对组进行排序):

库(data.table)
setDT(df)[,lappy(.SD,平均值),keyby=grp]
#>grp a b c d
#> 1:   1 3.079412 2.979412 2.979412 2.914706
#> 2:   2 3.029126 3.038835 2.967638 2.873786
#> 3:   3 2.854701 2.948718 2.951567 3.062678
让我们试着比较一下性能

库(dplyr)
图书馆(Purrryr)
库(数据表)
图书馆(长凳)
种子集(123)
n%切片行(“grp”)%%>%dmap(平均值),
data.table=dt[,lappy(.SD,平均值),keyby=grp],
检查=错误
)
#>#tibble:3 x 6
#>表达式最小中位数`itr/sec`mem_alloc`gc/sec`
#>               
#>1 dplyr 2.81ms 2.85ms 328。NA 17.3
#>2 Purrryr 7.96ms 8.04ms 123。NA 24.5
#>3.数据表596.33µs 707.91µs 1409。NA 10.3

完整性:使用dplyr v0.2
ddply
colwise
也可以这样做:

> ddply(df, .(grp), colwise(mean))
  grp        a    b        c        d
1   1 4.333333 4.00 1.000000 2.000000
2   2 2.000000 2.75 2.750000 2.750000
3   3 3.000000 4.00 4.333333 3.666667
但速度较慢,至少在这种情况下是这样:

> microbenchmark(ddply(df, .(grp), colwise(mean)), 
                  df %>% group_by(grp) %>% summarise_each(funs(mean)))
Unit: milliseconds
                                            expr      min       lq     mean
                ddply(df, .(grp), colwise(mean))     3.278002 3.331744 3.533835
 df %>% group_by(grp) %>% summarise_each(funs(mean)) 1.001789 1.031528 1.109337

   median       uq      max neval
 3.353633 3.378089 7.592209   100
 1.121954 1.133428 2.292216   100

我们可以在
dplyr 0.7.4
上使用
summary\u、
summary\u all
summary\u进行汇总。我们可以使用
vars
funs
参数设置多个列和函数,如下代码所示。funs公式的左侧指定给汇总变量的后缀。在
dplyr 0.7.4
中,
summary\u each
(和
mutate\u each
)已被弃用,因此我们无法使用这些函数

选项(scipen=100,dplyr.width=Inf,dplyr.print\u max=Inf)
图书馆(dplyr)
包装版本(“dplyr”)
# [1] ‘0.7.4’
种子集(123)
df%分组依据(grp)%>%
总结每个(.vars=字母[1:4],
.funs=c(mean=“mean”))
#“summary_each()”已弃用。
#改为使用'summary_all()'、'summary_at()'或'summary_if()'。
#要在一系列变量上映射funs,请使用summary_at()`
#错误:字符串必须与列名匹配。未知列:平均值
您应该更改为以下代码。以下代码都具有相同的结果。

#总结#
df%>%分组依据(grp)%>%
总结在(.vars=字母[1:4],
.funs=c(mean=“mean”))
df%>%分组依据(grp)%>%
在(.vars=名称(.)[1:4]处总结,
.funs=c(mean=“mean”))
df%>%分组依据(grp)%>%
在(.vars=vars(a,b,c,d)处总结,
.funs=c(mean=“mean”))
#总结
df%>%分组依据(grp)%>%
总结所有内容(.funs=c(mean=“mean”))
#总结
df%>%分组依据(grp)%>%
如果(.predicate=函数(x)是.numeric(x),则总结,
.funs=funs(mean=“mean”))
#一个tibble:3x5
#grp a_表示b_表示c_表示d_表示
#         
# 1     1   2.80   3.00    3.6   3.00
# 2     2   4.25   2.75    4.0   3.75
# 3     3   3.00   5.00    1.0   2.00
您还可以具有多个功能。

df%>%分组依据(grp)%>%
总结在(.vars=字母[1:2],
.funs=c(Mean=“Mean”,Sd=“Sd”))
#一个tibble:3x5
#grp a_表示b_表示a_Sd b_Sd
#              
# 1     1   2.80   3.00 1.4832397 1.870829
# 2     2   4.25   2.75 0.9574271 1.258306
#3 3.00 5.00不适用

所有的例子都很好,但我想我应该再添加一个来说明如何以“整洁”的格式工作来简化事情。现在,数据框是“宽”格式,这意味着变量“a”到“d”在列中表示。要获得“整洁”(或长)格式,可以使用
tidyr
包中的
gather()
,将列“a”到“d”中的变量转换为行。然后使用
group\u by()
summary()
函数获得每组的平均值。如果您想以较宽的格式显示数据,只需附加调用
spread()
函数即可


库(tidyverse)
#创建可复制的df
种子集(101)
df%
聚集(键=变量,值=值,a:d)%>%
分组依据(grp,变量)%>%
汇总(平均值=平均值))%>%
价差(可变、平均)
#>来源:本地数据帧[3 x 5]
#>组别:grp[3]
#> 
#>grp a b c d
#> *              
#> 1     1 3.000000   3.5 3.250000 3.250000
#> 2     2 1.666667   4.0 4.666667 2.666667
#> 3     3 3.333333   3.0 2.333333 2.333333

太棒了!如果列名和计数未知,是否有可能执行这些操作?例如,有3个或6个固定列而不是4个固定列?我认为这是
dplyr
中的一个TODO(比如
plyr
colwise
),请参见此处,了解当前相当棘手的解决方案:非常感谢你们两位!我可能会使用循环来迭代所有列。
dplyr
现在有了
summary\u每个
将对每个列进行操作
dplyr
现在已经用
summary>取代了
summary\u*
> microbenchmark(ddply(df, .(grp), colwise(mean)), 
                  df %>% group_by(grp) %>% summarise_each(funs(mean)))
Unit: milliseconds
                                            expr      min       lq     mean
                ddply(df, .(grp), colwise(mean))     3.278002 3.331744 3.533835
 df %>% group_by(grp) %>% summarise_each(funs(mean)) 1.001789 1.031528 1.109337

   median       uq      max neval
 3.353633 3.378089 7.592209   100
 1.121954 1.133428 2.292216   100
# summarise_at
df %>% group_by(grp) %>% 
  summarise_at(.vars = letters[1:4],
               .funs = c(mean="mean"))

df %>% group_by(grp) %>% 
  summarise_at(.vars = names(.)[1:4],
               .funs = c(mean="mean"))

df %>% group_by(grp) %>% 
  summarise_at(.vars = vars(a,b,c,d),
               .funs = c(mean="mean"))

# summarise_all
df %>% group_by(grp) %>% 
  summarise_all(.funs = c(mean="mean"))

# summarise_if
df %>% group_by(grp) %>% 
  summarise_if(.predicate = function(x) is.numeric(x),
               .funs = funs(mean="mean"))
# A tibble: 3 x 5
# grp a_mean b_mean c_mean d_mean
# <chr>  <dbl>  <dbl>  <dbl>  <dbl>
# 1     1   2.80   3.00    3.6   3.00
# 2     2   4.25   2.75    4.0   3.75
# 3     3   3.00   5.00    1.0   2.00
df %>% group_by(grp) %>% 
  summarise_at(.vars = letters[1:2],
               .funs = c(Mean="mean", Sd="sd"))
# A tibble: 3 x 5
# grp a_Mean b_Mean      a_Sd     b_Sd
# <chr>  <dbl>  <dbl>     <dbl>    <dbl>
# 1     1   2.80   3.00 1.4832397 1.870829
# 2     2   4.25   2.75 0.9574271 1.258306
# 3     3   3.00   5.00        NA       NA