【发布时间】:2011-03-09 18:57:06
【问题描述】:
我有一个包含 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")
我获得了良好的性能,以及一些可重用的优雅代码。
【问题讨论】:
-
this question 中有一大堆 plyr 优化技巧。另外,不要忘记您可以通过将
ddply链接到foreach包来并行运行它。 -
已经看到了 - 尝试了我喜欢的技巧,而不是我不喜欢的技巧。相反,我使用了上面的编辑,它使用了基础 R,保持相当灵活,并且执行速度很快(仍然不到 2 分钟)。仍然希望解释为什么这在 ddply 中很慢 - 喜欢语法和并行功能!
-
ddply太慢了,因为它适用于数据帧,不幸的是,数据帧相当慢。更快的方法直接使用向量,这要快得多 -
感谢哈德利的解释。