R中的多维数组的操作:apply vs data.table vs plyr(parallel)

时间:2014-10-16 09:12:24

标签: r multidimensional-array data.table plyr

在我的研究工作中,我通常会处理大型4D阵列(20-200万个元素)。 我正在努力提高计算的计算速度,寻求速度和简单性之间的最佳平衡。由于SO(见herehere

,我已经向前迈进了一步

现在,我正在尝试利用data.tableplyr这样的最新软件包。

让我们从以下内容开始:

D = c(100, 1000, 8) #x,y,t
d = array(rnorm(prod(D)), dim = D)

我想为每个x(第一维度)和y(第二维度)获取超过第90个百分位数的t的值。让我们用基数R来做:

system.time(
    q1 <- apply(d, c(1,2), function(x) {
        return(x >= quantile(x, .9, names = F))
        })
)    

在我的Macbook上大约十秒钟。我得到一个数组:

> dim(q1)
[1]    8  100 1000

apply奇怪地改变了维度的顺序,反正我现在不在乎)。现在我可以meltreshape2包)我的数组并将其用于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秒。现在我想试试plyrddply

system.time({
    q3 <- ddply(d_m, .(x, y), summarise, q = quantile(value, .9, names = F))
})

现在需要60秒。如果我转到dplyr我可以在十秒内再次进行相同的计算。

但是,我的问题如下:如何以更快的方式进行相同的计算?如果我考虑一个更大的矩阵(比如说大20倍),我可以使用data.table获得更快的计算{。{1}}函数,但是在相同的数量级(14分钟对10分钟)。 任何评论都非常感谢...

修改

我使用apply在c ++中实现了分位数函数,加快了八次计算速度。

1 个答案:

答案 0 :(得分:1)

正如@roland所建议的,加速代码的一种可能解决方案是实现更快版本的quantile函数。我花了一个小时来学习如何使用Rcpp来做到这一点,并且运行时间减少了八倍。我已经实现了type 7版本的分位数算法(默认选项)。 我们距离MATLAB性能还很远(讨论here),但就我而言,这是一个令人印象深刻的进步。我对我到目前为止所写的Rcpp代码并不感到自豪,我没有时间对其进行修改。无论如何,它工作(我用R函数检查了结果),所以如果你有兴趣,可以从here下载。