通过获取总和来聚合重复的行

tch*_*rty 4 r plyr data.table

继我的问题之后:
1.确定一组变量是否唯一地标识数据的每一行;
2. 根据给定的变量集标记所有重复的行,
我现在想通过获取它们的总和,根据给定的变量集合来汇总/合并所有重复的行.

解决方案1:

关于如何在这里执行此操作有一些指导,但是当存在构成索引的大量变量级别时,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)

解决方案2:

第二个解决方案是使用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.

Aru*_*run 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)]
Run Code Online (Sandbox Code Playgroud)

data.table版本1.9.2+还实现了一个函数setDT,使转换data.framesdata.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,plyrdata.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