【问题标题】:How does one aggregate and summarize data quickly?如何快速汇总和汇总数据?
【发布时间】:2011-12-05 01:38:42
【问题描述】:

我有一个标题如下所示的数据集:

PID Time Site Rep Count

我想将每个PID x Time x Site comboCountRep 相加

在生成的 data.frame 上,我想为 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)
}

这非常慢(原始 data.frame 是 510000 20)。有没有办法用 plyr 加快速度?

【问题讨论】:

  • 你没有说明为什么你有 A
  • 对,data.table 速度非常快(很高兴我了解了它)。 A 是多余的,是的。
  • 然后 A 行将解释为什么您的聚合如此缓慢。如果你只运行 B,它应该会很快。提供的 data.table 命令也删除了 REP。是您基本上在 A 中创建了一个与原始数据框大小相同的新数据框,这大大减慢了速度。

标签: r plyr data.table


【解决方案1】:

让我们看看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 提出的答案和 cmets 中提出的 @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更快!

【讨论】:

  • 如果你使用setDT(data)[,.(A = sum(Count), B = mean(Count)), by = 'PID,Time,Site']而不是创建副本会更快
  • 你检查过50-100GB benchmarks吗?
  • 还没有,在上下文中使用关于 OP 报告的大小的数据集似乎更有趣。
【解决方案2】:

您应该查看 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 确实运行得非常快!如何让这些列表 A 和 B 按 PIDTimeSite 排序(就像聚合一样)?
  • @Sangram 使用keyby 而不是by
  • @DavidArenburg 对非常大的数据表进行聚合分组的最快方法是什么?是上面的吗?当您使用键时,子集使用更快的二进制搜索是我的理解。虽然它使代码的可读性降低了一点
  • @robertevansanders,很可能对键控数据进行聚合会更快,但我认为我从未测试过它。
猜你喜欢
  • 1970-01-01
  • 2013-01-19
  • 1970-01-01
  • 2016-12-19
  • 2020-01-01
  • 1970-01-01
  • 2018-04-23
  • 2019-06-01
  • 1970-01-01
相关资源
最近更新 更多