继续我的问题:
1. Identifying whether a set of variables uniquely identifies each row of the data or not;
2. Tagging all rows that are duplicates in terms of a given set of variables,
我现在想用一组给定的变量来汇总/合并所有重复的行,取其总和。
关于如何执行此操作here有一些指导,但是当形成索引的变量级别很多时,推荐的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))
第二个解决方案是使用data.table
,并遵循建议here,我可以做
# data.table solution
indexVars = paste0('f', 1:4, sep = '')
dtDup = data.table(dfDup, key = indexVars)
dtDupAgg = dtDup[, list(data = sum(data)), by = key(dtDup)]
我有几个问题:
1.有没有办法让ddply
版本更快?
2. data.table
是否正确?我想检查,因为我是data.table
的新手。
答案 0 :(得分:7)
关于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)]
data.table
版本1.9.2+还实现了一个函数setDT
,可以通过引用将data.frames
转换为data.tables
(这意味着,没有副本,因此在转换中几乎没有时间,尤其适用于大型data.frames)。
所以,而不是做:
dtDup <- as.data.table(dfDup)
dtDup[...]
你可以这样做:
## data.table v1.9.2+
setDT(dfDup) ## faster than as.data.table(.)
dfDup[...] ## dfDup is now a data.table, converted by reference
关于你的第一个问题,plyr
并不知道它的速度。检查Why is plyr so slow?(以及那里的许多信息性评论)以获取更多信息。
也许您可能对dplyr
感兴趣,这比plyr
快几个数量级,但仍然比data.table
慢,恕我直言。这是等效的dplyr
版本:
dfDup %.% group_by(f1, f2, f3, f4) %.% summarise(data = sum(data))
以下是数据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
我真的没有耐心去运行plyr
版本(首次运行93秒后停止)。正如您所看到的,dplyr
比plyr
快得多,但比data.table
慢〜7倍。
检查结果是否相等:
all.equal(as.data.frame(ans1[order(f1,f2,f3,f4)]),
as.data.frame(ans2))
# [1] TRUE
HTH