我有一个130万行数据框,我需要将其汇总到区域和时间摘要中。 Plyr
的语法很简单,但实际上太慢了(我已经让ddply
运行了一个小时,而且它的完成率不到25%)。我正在寻找帮助将ddply
语法翻译成data.table
以利用其自豪的速度。
我的数据属于以下类型
library(plyr)
library(lubridate)
dat <- expand.grid(area = letters[1:2],
day = as.Date("2012-10-01") + c(0:10) * days(1),
type = paste("t", 1:2, sep=""))
dat$val <- runif(44)
我需要行计数(根据我的玩具数据在这里相等)和不同时期的val
变量的总和。
此ddply
来电给了我正在寻找的内容
count.and.sum <- function(i){
if(i$day >= as.Date("2012-10-02")){
k <- data.frame(c_1d = nrow(dat[dat$type == i$type &
dat$area == i$area &
dat$day %in% i$day - days(1),]),
c_2d = nrow(dat[dat$type == i$type &
dat$area == i$area &
dat$day %in% (i$day - c(1:2) * days(1)),]),
s_1d = sum(dat$val[dat$type == i$type &
dat$area == i$area &
dat$day %in% i$day - days(1)]),
s_2d = sum(dat$val[dat$type == i$type &
dat$area == i$area &
dat$day %in% (i$day - c(1:2) * days(1))]))
return(k)
}
}
ddply(dat, .(area, day, type), count.and.sum)[1:10,]
非常感谢您提供的任何data.table
语法。
答案 0 :(得分:2)
首先,你的函数非常低效,并且缺乏对传递给plyr的函数应该是什么样的理解。对于ddply(),它应该将通用数据帧作为输入并输出数据帧。在这种情况下,“泛型”是指一种数据框,它将被生成为由分组变量的级别组合定义的任何一个“分裂”。你的功能应该更像这样:
count.and.sum <- function(d) data.frame(n = length(d$val), valsum = sum(d$val))
分组变量组合在ddply()调用中处理。
其次,您的ddply()
调用会创建一个行数据框,因为每个观察都与区域,日期和类型的唯一组合相关联。 ddply()
这个玩具示例的更现实的应用是白天总结:
使用summarise
作为'apply'函数的直接方法:
ddply(dat, .(day), summarise, nrow = length(val), valsum = sum(val))
使用count.and.sum
:
ddply(dat, .(day), count.and.sum)
这很可能比您的count.and.sum
版本快得多。
对于等效的data.table版本(不一定是最有效的),试试这个:
library(data.table)
DT <- data.table(dat, key = c('area', 'day', 'type'))
DT[, list(n = length(val), valsum = sum(val)), by = 'day']
这是一个稍微复杂的玩具示例,带有100K观测值:
set.seed(5490)
dat2 <- data.frame(area = sample(letters[1:2], 1e5, replace = TRUE),
day = sample(as.Date("2012-10-01") + c(0:10) * days(1),
1e5, replace = TRUE),
type = sample(paste0("t", 1:2), 1e5, replace = TRUE),
val = runif(1e5))
system.time(u <- ddply(dat2, .(area, day, type), summarise,
n = length(val), valsum = sum(val)))
DT2 <- data.table(dat2, key = c('area', 'day', 'type'))
system.time(v <- DT2[, list(n = length(val), valsum = sum(val)), by = key(DT)])
identical(u, as.data.frame(v))
在我的系统上,data.table
版本比plyr
版本快4.5倍(plyr已经过了0.09秒,data.table则为0.02)。