在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)
)