继我的问题之后:
1.确定一组变量是否唯一地标识数据的每一行;
2. 根据给定的变量集标记所有重复的行,
我现在想通过获取它们的总和,根据给定的变量集合来汇总/合并所有重复的行.
关于如何在这里执行此操作有一些指导,但是当存在构成索引的大量变量级别时,ddply推荐的方法很慢,因为在我尝试标记所有重复项的情况下通过一组给定的变量.
# Values of (f1, f2, f3, f4) uniquely identify observations
dfUnique = expand.grid(f1 = factor(1:16),
f2 = factor(1:41),
f3 = factor(1:2),
f4 = factor(1:104))
# sample some extra rows and rbind them
dfDup = rbind(dfUnique, dfUnique[sample(1:nrow(dfUnique), 100), ])
# dummy data
dfDup$data = rnorm(nrow(dfDup))
# aggregate the duplicate rows by taking the sum
dfDupAgg = ddply(dfDup, .(f1, f2, f3, f4), summarise, data = sum(data))
Run Code Online (Sandbox Code Playgroud)
第二个解决方案是使用data.table,并遵循这里的建议,我可以做到
# data.table solution
indexVars = paste0('f', 1:4, sep = '')
dtDup = data.table(dfDup, key = indexVars)
dtDupAgg = dtDup[, list(data = sum(data)), by = key(dtDup)]
Run Code Online (Sandbox Code Playgroud)
我有几个问题:
1.有没有办法让ddply版本更快?
2.是对的data.table吗?我想检查,因为我是新手data.table.
关于您的data.table解决方案,您无需为聚合操作设置密钥.你可以直接做:
indexVars = paste0('f', 1:4, sep = '')
dtDup <- as.data.table(dfDup) ## faster than data.table(.)
dtDupAgg = dtDup[, list(data = sum(data)), by = c(indexVars)]
Run Code Online (Sandbox Code Playgroud)
data.table版本1.9.2+还实现了一个函数setDT,使转换data.frames到data.tables 由参考(这意味着,没有复制,并且因此需要在转换几乎没有时间上大data.frames特别有用).
所以,而不是做:
dtDup <- as.data.table(dfDup)
dtDup[...]
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
## data.table v1.9.2+
setDT(dfDup) ## faster than as.data.table(.)
dfDup[...] ## dfDup is now a data.table, converted by reference
Run Code Online (Sandbox Code Playgroud)
关于你的第一个问题,plyr不知道它的速度.检查为什么plyr这么慢?(以及那里的许多信息性评论)了解更多信息.
也许你可能感兴趣dplyr,plyr比data.table恕我直言的速度要快几个数量级,但速度要慢一些.这是等效dplyr版本:
dfDup %.% group_by(f1, f2, f3, f4) %.% summarise(data = sum(data))
Run Code Online (Sandbox Code Playgroud)
这是数据之间data.table和之间的基准dplyr(所有时间最少连续三次):
## data.table v1.9.2+
system.time(ans1 <- dtDup[, list(data=sum(data)), by=c(indexVars)])
# user system elapsed
# 0.049 0.009 0.057
## dplyr (commit ~1360 from github)
system.time(ans2 <- dfDup %.% group_by(f1, f2, f3, f4) %.% summarise(data = sum(data)))
# user system elapsed
# 0.374 0.013 0.389
Run Code Online (Sandbox Code Playgroud)
我真的没有耐心去运行plyr版本(第一次运行93秒后停止).正如你所看到dplyr的要快得多plyr,但比data.table这里慢约7倍.
检查结果是否相等以确定:
all.equal(as.data.frame(ans1[order(f1,f2,f3,f4)]),
as.data.frame(ans2))
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
HTH