使用dplyr汇总多个列?
我对dplyr语法有点纠结。我有一个包含不同变量和一个分组变量的数据框。现在我想用R中的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),
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.2ddply
和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