我有一个模拟,有一个巨大的聚合和合并步骤的权利,在中间。我使用plyr的ddply()函数对这个过程进行了原型化,它可以很好地满足我的大部分需求。但是我需要这个聚合步骤更快,因为我必须运行10 K模拟。我已经在并行扩展模拟,但如果这一步更快,我可以大大减少我需要的节点数量。
下面是我试图做的一个合理的简化:
library(Hmisc)
# Set up some example data
year <- sample(1970:2008, 1e6, rep=T)
state <- sample(1:50, 1e6, rep=T)
group1 <- sample(1:6, 1e6, rep=T)
group2 <- sample(1:3, 1e6, rep=T)
myFact <- rnorm(100, 15, 1e6)
weights <- rnorm(1e6)
myDF <- data.frame(year, state, group1, group2, myFact, weights)
# this is the step I want to make faster
system.time(aggregateDF <- ddply(myDF, c("year", "state", "group1", "group2"),
function(df) wtd.mean(df$myFact, weights=df$weights)
)
)
所有的提示或建议都很感激!
6条答案
按热度按时间7fhtutme1#
代替普通的R Dataframe ,你可以使用一个不可变的 Dataframe ,当你子集时,它会返回指向原始数据的指针,并且速度会快得多:
如果我写一个plyr函数来定制这种情况,我会这样做:
它的速度要快得多,因为它避免了复制数据,只在计算时提取每次计算所需的子集。将数据切换为矩阵形式提供了另一种速度提升,因为矩阵子集化比 Dataframe 子集化快得多。
cbeh67ev2#
2倍的加速和更简洁的代码:
我的第一篇文章,所以请善待;)
从
data.table
v1.9.2中,导出了setDT
函数,该函数将通过引用 * 将data.frame
转换为data.table
*(与data.table
的说法保持一致-所有set*
函数都通过引用修改对象)。这意味着没有不必要的复制,因此速度很快。你可以计时,但会疏忽大意。这与上面OP的解决方案的1.264秒相反,其中
data.table(.)
用于创建dtb
。h7appiyu3#
我会用基地R来侧写
在我的机器上,它需要5秒,而原始代码需要67秒。
EDIT刚刚发现
rowsum
函数的另一个加速:需要3秒!
9bfwbjaz4#
您使用的是最新版本的Plyr吗(注意:这还没有使它的所有CRAN镜子呢)?如果是这样的话,您可以并行运行此操作。
下面是llply的例子,但同样的道理也适用于ddply:
好吧,其他的循环方法更糟糕,所以这可能需要(a)C/C++代码或(b)对如何做这件事进行更根本的重新思考。我甚至没有尝试使用
by()
,因为根据我的经验,这非常慢。watbbzwu5#
当应用的函数有多个向量参数时,我通常使用索引向量和tapply:
我使用一个简单的 Package 器,它是等效的,但隐藏了混乱:
编辑以包括下面的tmapply以供评论:
bnl4lu3b6#
可能最快的解决方案是使用
collapse::fgroup_by
。它比data.table
快8倍: