如何快速汇总和总结数据?

15

我有一个数据集,其表头如下:

PID Time Site Rep Count

我想要根据每个PID x Time x Site combo中的RepCount进行求和。

在得到的数据框中,我想要获得PID x Time x Site组合的Count平均值。

当前函数如下:

dummy <- function (data)
{
A<-aggregate(Count~PID+Time+Site+Rep,data=data,function(x){sum(na.omit(x))})
B<-aggregate(Count~PID+Time+Site,data=A,mean)
return (B)
}

这个操作非常缓慢(原始的数据框大小为 510000 20)。是否有一种使用 plyr 加速此操作的方法?


你没有说明为什么要有A<-这一行。你是在确保有一个加权吗?为了满足你所说的标准,你只需要B<-这一行。(plyr不会让它更快,但data.frame会) - John
没错,data.table非常快(我很高兴学会了它)。A是多余的,是的。 - Maiasaura
那么A行将解释为什么你的聚合速度如此缓慢。如果你只运行B,它应该很快。提供的data.table命令也会删除REP。问题在于,在A中基本上创建了一个与原始数据框相同大小的新数据框,这就是导致速度变慢的原因。 - John
2个回答

26

如果您需要在大型数据框上进行更快的聚合操作,建议使用data.table包。对于您的问题,解决方案如下:

library(data.table)
data_t = data.table(data_tab)
ans = data_t[,list(A = sum(count), B = mean(count)), by = 'PID,Time,Site']

哇,data.table 真的运行得非常快!如何按 PIDTimeSite(就像聚合一样)对这些列表 A 和 B 进行排序? - exAres
5
请使用keyby代替by - David Arenburg
@DavidArenburg 什么是处理非常大的数据表进行分组聚合的最快方法?上述方法是否可行?使用键时,子集使用二进制搜索,这是我理解中更快的方法。尽管这使得代码有点难以阅读。 - wolfsatthedoor
@robertevansanders,按键数据进行聚合很可能更快,但我不认为我曾经测试过它。 - David Arenburg

9

让我们看看data.table有多快,并将其与使用dplyr进行比较。以下大致是在dplyr中执行的方式。

data %>% group_by(PID, Time, Site, Rep) %>%
    summarise(totalCount = sum(Count)) %>%
    group_by(PID, Time, Site) %>% 
    summarise(mean(totalCount))

根据问题的具体解释,可能是这样:

    data %>% group_by(PID, Time, Site) %>%
        summarise(totalCount = sum(Count), meanCount = mean(Count)  

这是一个完整的例子,展示了这些替代方法与@Ramnath提出的答案以及@David Arenburg在评论中提出的答案之间的区别,我认为这个例子等同于第二个dplyr语句。
nrow <- 510000
data <- data.frame(PID = sample(letters, nrow, replace = TRUE), 
                   Time = sample(letters, nrow, replace = TRUE),
                   Site = sample(letters, nrow, replace = TRUE),
                   Rep = rnorm(nrow),
                   Count = rpois(nrow, 100))


library(dplyr)
library(data.table)

Rprof(tf1 <- tempfile())
ans <- data %>% group_by(PID, Time, Site, Rep) %>%
    summarise(totalCount = sum(Count)) %>%
    group_by(PID, Time, Site) %>% 
    summarise(mean(totalCount))
Rprof()
summaryRprof(tf1)  #reports 1.68 sec sampling time

Rprof(tf2 <- tempfile())
ans <- data %>% group_by(PID, Time, Site, Rep) %>%
    summarise(total = sum(Count), meanCount = mean(Count)) 
Rprof()
summaryRprof(tf2)  # reports 1.60 seconds

Rprof(tf3 <- tempfile())
data_t = data.table(data)
ans = data_t[,list(A = sum(Count), B = mean(Count)), by = 'PID,Time,Site']
Rprof()
summaryRprof(tf3)  #reports 0.06 seconds

Rprof(tf4 <- tempfile())
ans <- setDT(data)[,.(A = sum(Count), B = mean(Count)), by = 'PID,Time,Site']
Rprof()
summaryRprof(tf4)  #reports 0.02 seconds

数据表法非常快,而setDT更快!

2
如果您使用setDT(data)[,。(A = sum(Count),B = mean(Count)),by ='PID,Time,Site']而不是创建副本,它将更快。 - David Arenburg
1
你有查看过50-100GB基准测试吗? - Arun
暂时还没有,从上下文来看,使用OP报告的数据集似乎更有趣。 - vpipkt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接