如何加快总结和ddply?

时间:2011-03-09 18:57:06

标签: r plyr

我有一个包含200万行和15列的数据框。我想用ddply对这些列中的3个进行分组(所有3个是因子,并且这些因子有780,000个唯一组合),并获得3列的加权平均值(权重由我的数据集定义)。以下是相当快的:

system.time(a2 <- aggregate(cbind(col1,col2,col3) ~ fac1 + fac2 + fac3, data=aggdf, FUN=mean))
   user  system elapsed 
 91.358   4.747 115.727 

问题是我想使用weighted.mean而不是mean来计算我的聚合列。

如果我在同一个数据框上尝试以下ddply(请注意,我转换为不可变),以下内容在20分钟后没有完成:

x <- ddply(idata.frame(aggdf), 
       c("fac1","fac2","fac3"), 
       summarise, 
       w=sum(w), 
       col1=weighted.mean(col1, w), 
       col2=weighted.mean(col2, w),
       col3=weighted.mean(col3, w))

此操作似乎是CPU饥饿,但不是非常密集RAM。

编辑: 所以我最后编写了这个小函数,它通过利用加权平均值的某些属性来“欺骗”一些,并对整个对象进行乘法和除法,而不是对切片进行乘法和除法。

weighted_mean_cols <- function(df, bycols, aggcols, weightcol) {
    df[,aggcols] <- df[,aggcols]*df[,weightcol]
    df <- aggregate(df[,c(weightcol, aggcols)], by=as.list(df[,bycols]), sum)
    df[,aggcols] <- df[,aggcols]/df[,weightcol]
    df
}

我跑的时候:

a2 <- weighted_mean_cols(aggdf, c("fac1","fac2","fac3"), c("col1","col2","col3"),"w")

我获得了良好的性能,并且有些可重用,优雅的代码。

2 个答案:

答案 0 :(得分:5)

尽管ddply因代码优雅和易用而难以击败,但我发现对于大数据,tapply要快得多。在你的情况下,我会使用

do.call("cbind", list((w <- tapply(..)), tapply(..)))

对于问题的点和可能的错误理解感到抱歉;但我有点匆忙,必须在大约五分钟内赶上公共汽车!

答案 1 :(得分:2)

如果您要使用编辑,为什么不使用rowsum并节省几分钟的执行时间?

nr <- 2e6
nc <- 3
aggdf <- data.frame(matrix(rnorm(nr*nc),nr,nc),
                    matrix(sample(100,nr*nc,TRUE),nr,nc), rnorm(nr))
colnames(aggdf) <- c("col1","col2","col3","fac1","fac2","fac3","w")

system.time({
aggsums <- rowsum(data.frame(aggdf[,c("col1","col2","col3")]*aggdf$w,w=aggdf$w), 
  interaction(aggdf[,c("fac1","fac2","fac3")]))
agg_wtd_mean <- aggsums[,1:3]/aggsums[,4]
})
#   user  system elapsed 
#  16.21    0.77   16.99 
相关问题