R 分组计算平均数
我有一个大数据框,看起来像这样:R 分组计算平均数,r,dataframe,r-faq,R,Dataframe,R Faq,我有一个大数据框,看起来像这样: df <- data.frame(dive = factor(sample(c("dive1","dive2"), 10, replace=TRUE)), speed = runif(10) ) > df dive speed 1 dive1 0.80668490 2 dive1 0.53349584 3 dive2 0
df <- data.frame(dive = factor(sample(c("dive1","dive2"), 10, replace=TRUE)),
speed = runif(10)
)
> df
dive speed
1 dive1 0.80668490
2 dive1 0.53349584
3 dive2 0.07571784
4 dive2 0.39518628
5 dive1 0.84557955
6 dive1 0.69121443
7 dive1 0.38124950
8 dive2 0.22536126
9 dive1 0.04704750
10 dive2 0.93561651
df
潜水速度
1第1部分0.80668490
2第1部分0.53349584
3第2部分0.07571784
4第2部分0.39518628
5第1部分0.84557955
6第1部分0.69121443
7第1部分0.38124950
8第2部分0.22536126
9第1部分0.04704750
10第2部分0.93561651
我的目标是当另一列等于某个值时,获得一列中值的平均值,并对所有值重复此操作。i、 e.在上面的示例中,我想返回
列速度
的每个唯一值的平均值下降
。因此,当dive==dive1
时,speed
的平均值为dive
的每一个值,以此类推,在R中有很多方法可以做到这一点。具体地说,通过,聚合,拆分,和plyr
,转换,塔普利
,数据。表,,
,等等
aggregate(speed~dive,data=df,FUN=mean)
dive speed
1 dive1 0.7059729
2 dive2 0.5473777
从广义上讲,这些问题的形式是分裂-应用-合并。Hadley Wickham写了一篇文章,可以让你更深入地了解整个问题类别,这篇文章非常值得一读。他的plyr
包实现了通用数据结构的策略,而dplyr
是针对数据帧调整的较新实现性能。它们允许解决相同形式的问题,但比这个问题更复杂。作为解决数据操作问题的通用工具,它们非常值得学习
在非常大的数据集上,性能是一个问题,因此很难找到基于data.table
的解决方案。但是,如果您只处理中型或小型数据集,那么花时间学习data.table
可能不值得dplyr也可以很快,因此如果您想加快速度,但不太需要data.table的可伸缩性,那么它是一个不错的选择
下面的许多其他解决方案不需要任何附加包。其中一些在中大型数据集上的速度甚至相当快。他们的主要缺点要么是隐喻,要么是灵活性。我所说的隐喻是指,它是一种工具,是为被强迫以“聪明”的方式解决这类特殊问题而设计的。我所说的灵活性,是指他们缺乏解决范围如此广泛的类似问题的能力,或者缺乏轻松产生整洁输出的能力
例子
base
函数
tapply
:
tapply(df$speed, df$dive, mean)
# dive1 dive2
# 0.5419921 0.5103974
df %>% group_by(dive) %>% summarise(percentage = mean(speed))
Source: local data frame [2 x 2]
dive percentage
1 dive1 0.4777462
2 dive2 0.6726483
聚合
:
library(data.table)
setDT(df)[ , .(mean_speed = mean(speed)), by = dive]
# dive mean_speed
# 1: dive1 0.5419921
# 2: dive2 0.5103974
library(dplyr)
group_by(df, dive) %>% summarize(m = mean(speed))
aggregate
接收data.frames,输出data.frames,并使用公式接口
aggregate( speed ~ dive, df, mean )
# dive speed
# 1 dive1 0.5790946
# 2 dive2 0.4864489
作者
:
library(data.table)
setDT(df)[ , .(mean_speed = mean(speed)), by = dive]
# dive mean_speed
# 1: dive1 0.5419921
# 2: dive2 0.5103974
library(dplyr)
group_by(df, dive) %>% summarize(m = mean(speed))
它以最用户友好的形式接受向量并对其应用函数。但是,它的输出不是一种非常可操作的形式:
res.by <- by(df$speed, df$dive, mean)
res.by
# df$dive: dive1
# [1] 0.5790946
# ---------------------------------------
# df$dive: dive2
# [1] 0.4864489
拆分
:
library(data.table)
setDT(df)[ , .(mean_speed = mean(speed)), by = dive]
# dive mean_speed
# 1: dive1 0.5419921
# 2: dive2 0.5103974
library(dplyr)
group_by(df, dive) %>% summarize(m = mean(speed))
顾名思义,它只执行拆分应用联合收割机策略的“拆分”部分。为了使其余的工作正常,我将编写一个小函数,它使用apply combine的sapply
<代码>sapply
自动尽可能简化结果。在我们的例子中,这意味着一个向量而不是一个data.frame,因为我们只有一维的结果
splitmean <- function(df) {
s <- split( df, df$dive)
sapply( s, function(x) mean(x$speed) )
}
splitmean(df)
# dive1 dive2
# 0.5790946 0.4864489
dplyr
:
library(data.table)
setDT(df)[ , .(mean_speed = mean(speed)), by = dive]
# dive mean_speed
# 1: dive1 0.5419921
# 2: dive2 0.5103974
library(dplyr)
group_by(df, dive) %>% summarize(m = mean(speed))
plyr
(dplyr
的前光标)
以下是关于plyr的plyr
:
使用base
R函数(如split
和
apply
函数系列),但是plyr
使这一切变得更容易
与:
- 完全一致的名称、参数和输出
- 通过
foreach
包方便地进行并行化
- 数据的输入和输出。帧、矩阵和列表
- 用于跟踪长期运行操作的进度条
- 内置的错误恢复和信息性错误消息
- 在所有转换中维护的标签
换句话说,如果您学习了一种用于拆分应用联合收割机操作的工具,那么它应该是plyr
library(plyr)
res.plyr <- ddply( df, .(dive), function(x) mean(x$speed) )
res.plyr
# dive V1
# 1 dive1 0.5790946
# 2 dive2 0.4864489
基准
10行,2组
然后使用对数据进行操作的data.table
或dplyr
。某些方法(aggregate
和dcast
)开始显得非常缓慢
1000万行,1000组
如果有更多的组,则差异会更明显。1000组和相同的10^7行:
df <- data.frame(dive=factor(sample(seq(1000),10^7,replace=TRUE)),speed=runif(10^7))
dt <- data.table(df)
setkey(dt,dive)
# then run the same microbenchmark as above
print(m3, signif = 3)
Unit: milliseconds
expr min lq mean median uq max neval cld
by(df$speed, df$dive, mean) 776 791 816.2 810 828 925 100 b
aggregate(speed ~ dive, df, mean) 11200 11400 11460.2 11400 11500 12000 100 f
splitmean(df) 5940 6450 7562.4 7470 8370 11200 100 e
ddply(df, .(dive), function(x) mean(x$speed)) 1220 1250 1279.1 1280 1300 1440 100 c
dcast(melt(df), variable ~ dive, mean) 2110 2190 2267.8 2250 2290 2750 100 d
dt[, mean(speed), by = dive] 110 111 113.5 111 113 143 100 a
summarize(group_by(df, dive), m = mean(speed)) 625 630 637.1 633 644 701 100 b
summarize(group_by(dt, dive), m = mean(speed)) 129 130 137.3 131 142 213 100 a
autoplot(m3)
df2015年使用dplyr更新:
tapply(df$speed, df$dive, mean)
# dive1 dive2
# 0.5419921 0.5103974
df %>% group_by(dive) %>% summarise(percentage = mean(speed))
Source: local data frame [2 x 2]
dive percentage
1 dive1 0.4777462
2 dive2 0.6726483
我们已经有大量的选项可供选择,从mosaic
包中再添加一个选项
mosaic::mean(speed~dive, data = df)
#dive1 dive2
#0.579 0.440
这将返回一个命名的数字向量,如果需要一个数据帧,我们可以将其包装在堆栈中
stack(mosaic::mean(speed~dive, data = df))
# values ind
#1 0.579 dive1
#2 0.440 dive2
数据
set.seed(123)
df <- data.frame(dive=factor(sample(c("dive1","dive2"),10,replace=TRUE)),
speed=runif(10))
set.seed(123)
df添加替代的base R方法,在各种情况下保持快速
rowsummean <- function(df) {
rowsum(df$speed, df$dive) / tabulate(df$dive)
}
rowsummean使用collapse
library(collapse)
library(magrittr)
df %>%
fgroup_by(dive) %>%
fsummarise(speed = fmean(speed))
# dive speed
#1 dive1 0.5788479
#2 dive2 0.4401514
数据
set.seed(123)
df哇…非常感谢这是一个巨大的帮助。聚合函数工作得很好,微基准库对于我的绘图非常适合。再次感谢!此外,microbenchmark
软件包对事物进行了基准测试。这是ggplot2
,它实际上在那里制作了一个绘图(这是一个很棒的包)。+10好的,很好。这更像是有1000个小组。非常感谢你补充这一点。我将在接下来的两周内休假,这样你就可以从我的窃听中好好休息一下,听到:-)@Gregor nice你会松一口气的!非常感谢。看起来很漂亮,而且早就该更新dplyr了。显示带有/不带有数据的dplyr
。表
。真是太棒了。这是一个多么优秀、精确、全面的答案啊。荣誉。关于如何拆分应用合并但保留结果的相关问题