【发布时间】:2014-10-16 09:12:23
【问题描述】:
在我的研究工作中,我通常处理大型 4D 数组(20-2 亿个元素)。 我正在尝试提高计算的计算速度,以寻找速度和简单性之间的最佳折衷。多亏了 SO,我已经向前迈出了一步(请参阅 here 和 here)
现在,我正在尝试利用最新的软件包,例如 data.table 和 plyr。
让我们从以下内容开始:
D = c(100, 1000, 8) #x,y,t
d = array(rnorm(prod(D)), dim = D)
我想为每个x(第一维)和y(第二维)获取t 高于第90 个百分位的值。让我们用基础 R 来做:
system.time(
q1 <- apply(d, c(1,2), function(x) {
return(x >= quantile(x, .9, names = F))
})
)
在我的 Macbook 上大约需要 10 秒。我得到一个数组:
> dim(q1)
[1] 8 100 1000
(apply 奇怪地改变了尺寸的顺序,反正我现在不在乎)。现在我可以melt(reshape2 打包)我的数组并将其用于data.table:
> d_m = melt(d)
> colnames(d_m) = c('x', 'y', 't', 'value')
> d_t = data.table(d_m)
然后我做一些 data.table “魔术”:
system.time({
q2 = d_t[,q := quantile(value, .9, names = F), by="x,y"][,ev := value > q]
})
计算现在只需不到 10 秒。现在我想试试plyr 和ddply:
system.time({
q3 <- ddply(d_m, .(x, y), summarise, q = quantile(value, .9, names = F))
})
现在,需要 60 秒。如果我移动到dplyr,我可以在十秒内再次进行相同的计算。
但是,我的问题如下:您会如何以更快的方式进行相同的计算?如果我考虑一个更大的矩阵(比如大 20 倍),我使用 data.table wrt apply 函数获得更快的计算,但在相同的数量级(14 分钟对 10 分钟)。
任何评论都非常感谢......
编辑
我已经使用Rcpp 在 c++ 中实现了分位数函数,将计算速度提高了八倍。
【问题讨论】:
-
我怀疑你的瓶颈是
quantile而不是用于“split-apply-combine”的函数。分析您的代码。可能您需要编写一个更快的quantile函数(它目前在 R 中实现,因此速度不是很快)。看看 Rcpp。 -
你是对的。我刚刚花了一个小时来学习如何使用 Rcpp 复制 R 分位数算法。我已经获得了八倍的加速。
标签: r multidimensional-array data.table plyr