【发布时间】:2016-11-26 01:06:30
【问题描述】:
在 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 包中的一个函数,它返回一个列表列表,其中一个特定的列表 $fitted 长度为 1368,用于从每个循环增量中构造新数组。
虽然这个循环完美无缺,但它需要相当长的时间来计算。我读过foreach可用于并行化for循环。
但是,我不明白如何实现新数组的嵌套和组装,以使新旧数组的名称一致。
(最后,我希望能够使用as.data.frame.table() 将旧数组和新数组都转换为“平面”长面板数据框,并将它们沿它们的三个维度合并。 )
对于如何使用并行计算实现所需输出的任何帮助,我们将不胜感激!
干杯
立方汤姆
【问题讨论】:
-
我真的不知道你想做什么 (reproducible example!),但你是否考虑过使用在 n 维数组中通用的
apply()?apply()的第二个参数定义了应用函数的维度,例如apply( old.array , 1:2 , FUN = function(x) paste0(x) )以在数组的第三维上应用paste0()函数为例。 -
谢谢西蒙,我听从了你的建议,让我的例子可以重现。
-
我也尝试过使用 apply:
new2.array <- apply(old.array , 1:2 , FUN = function(x) spi(ts(x, freq=12, start=c(1901,1)), 1, na.rm = T) ),它非常快,但只给了我一个包含 72*36=2592 个元素的矩阵,每个元素都是 8 个元素的列表。我只对这 8 个中的第二个 ($fitted),它是与 d3 上的每个条目对应的所需函数值的列表。 -
如果我理解正确,那么您可以这样做:
new2.array <- apply(old.array , 1:2 , FUN = function(x) spi(ts(x, freq=12, start=c(1901,1)), 1, na.rm = T)$fitted ) -
这解决了嵌套列表问题!但是,尺寸尚未按正确的顺序排列。将所有内容包装在
aperm中会有所帮助,这样结果与我的循环示例相同。使用 tictoc 测量执行时间在这个解决方案上给了我 36.51 秒,而在我的循环可执行示例上为 39.88 秒。将实际数据中的每个维度乘以 10,这将是一个显着的改进(尽管诚然没有我希望的那么大)。谢谢西蒙!
标签: arrays r multidimensional-array foreach parallel-processing