首页 > 解决方案 > 当按两个变量分组时,tapply() 和 acast() 非常慢且占用内存

问题描述

我刚刚注意到,tapply()reshape2::acast()按两个变量分组时,在场景中超级慢且消耗内存!

看这个例子:

#download data and functions for monitoring time & memory
download.file("http://artax.karlin.mff.cuni.cz/~ttel5535/pub/so/tapply,reshape2_slow/tapply,reshape_slow.Rdata", "tapply,reshape_slow.Rdata", mode="wb")
load(file = "tapply,reshape_slow.Rdata")

require(reshape2)
mstart()
xx <- acast(bb, fi ~ gi, sum, value.var = "hour")
mstop()
#   user  system elapsed 
#   6.58    0.79    7.90 
#max memory used: 911.2Mb.

令人惊讶的是非常缓慢和内存贪婪!只是为了显示数据的属性:

nrow(bb)
#[1] 9467
dim(xx)
#[1] 4850 1492
print(object.size(xx), units = "Mb")
#28 Mb

现在tapply()

mstart()
xx2 <- tapply(bb$hour, list(bb$fi, bb$gi), sum, default = 0)
mstop()
#   user  system elapsed 
#   6.45    2.36    9.44 
#max memory used: 1135.9Mb.

更慢,更贪内存!

现在,比较一下,当分组是由 SQLite 完成时的解决方案,并且 acast() 仅用于重塑:

require(sqldf)
mstart()
xx3_0 <- sqldf("select fi, gi, sum(hour) as sum from bb group by fi, gi")
xx3 <- acast(xx3_0, fi ~ gi, fill = 0, value.var = "sum")
mstop()
#   user  system elapsed 
#   0.22    0.05    0.28 
#max memory used: 174.1Mb.

通常,我对几乎所有数据操作都使用 sqldf,但现在我想通过使用基本函数使其“更容易”:-) 但现在我真的很惊讶这些函数的性能非常糟糕!还没有人注意到吗?还是我用错了?

标签: rreshape2sqldftapply

解决方案


推荐阅读