R中三维数组上循环的并行嵌套



在Windows机器上使用R,我目前正在3D阵列(720x360x1368)上运行一个嵌套循环,该循环通过d1和d2,在d3上应用一个函数,并将输出组装到一个维度相似的新阵列。

在下面的可复制示例中,我将维度减少了10倍,以加快执行速度。

library(SPEI)
old.array = array(abs(rnorm(50)), dim=c(72,36,136))
new.array = array(dim=c(72,36,136))
for (i in 1:72) {
  for (j in 1:36) {
    new.listoflists <- spi(ts(old.array[i,j,], freq=12, start=c(1901,1)), 1, na.rm = T)
    new.array[i,j,] = new.listoflists$fitted
  }
}

其中,spi()是来自SPEI包的函数,返回列表列表,其中从每个循环增量使用长度为1368的一个特定列表$fitted来cunstruct新数组。

虽然这个循环可以完美地工作,但它需要相当长的时间来计算。我已经读到foreach可以用于并行化for循环。

然而,我不明白如何实现新阵列的嵌套和组装,从而使新旧阵列的dimname一致。

(最后,我希望能够使用as.data.frame.table()将新旧阵列转换为"平面"长面板数据帧,并将它们沿三维合并。)

关于如何使用并行计算实现所需输出的任何帮助都将不胜感激!

干杯
CubicTom

如果有一个可复制的例子会更好,下面是我想到的:

首先创建集群以使用

cl <- makeCluster(6, type = "SOCK")
registerDoSNOW(cl)

然后创建循环并关闭集群:

zz <- foreach(i = 1:720, .combine = c) %:% 
foreach(j = 1:360, .combine = c ) %dopar% {
new.listoflists <- FUN(old.array[i,j,])
new.array[i,j,] <- new.listoflists$list
}
stopCluster(cl)

这将创建一个列表zz,其中包含new.array[i,j,]的每一次迭代,然后您可以使用将它们绑定在一起

new.obj <- plyr::ldply(zz, data.frame)

希望这对你有帮助!

我没有像你的问题那样使用那么多维度,因为我想确保行为是正确的。所以这里我使用mapply,它接受多个参数。结果是一个结果列表。然后我用matrix()把它包装起来,得到你想要的尺寸。请注意,i使用重复,j每次使用。这一点非常关键,因为matrix()先按行放入条目,然后在达到行数时换行到下一列。

new.array = array(1:(5*10*4), dim=c(5,10,4))
# FUN: function which returns lists of 
FUN <- function(x){
    list(lapply(x, rep, times=3))
}
# result of the computation
result <- matrix(
    mapply(
        function(i,j,...){
            FUN(new.array[i,j,])
        }
        ,i = rep(1:nrow(new.array),times=ncol(new.array))
        ,j = rep(1:ncol(new.array),each=nrow(new.array))
        ,new.array=new.array
    )
    ,nrow=nrow(new.array)
    ,ncol=ncol(new.array)
)

相关内容

  • 没有找到相关文章

最新更新