R-加速数组维度上的循环
我正在使用具有维度的数组R-加速数组维度上的循环,r,performance,for-loop,multidimensional-array,R,Performance,For Loop,Multidimensional Array,我正在使用具有维度的数组 [1] 290 259 55 4 对于最后三个维度的每次重复,我想对第一维度的290个元素执行滚动平均,将元素数量减少到289个。最后,我需要用更新的值创建一个数据帧 下面的代码实现了我需要的功能,但运行起来需要很长时间(实际上,我必须在结束之前中断它) 图书馆(动物园) #生成与我的维度相同的随机数据 my.array在前面,您正遭受R的地狱()的第二个循环:不断增长的对象。每次调用rbind,它都会生成帧的完整副本,进行r绑定,然后覆盖原始变量名上的完整副本
[1] 290 259 55 4
对于最后三个维度的每次重复,我想对第一维度的290个元素执行滚动平均,将元素数量减少到289个。最后,我需要用更新的值创建一个数据帧
下面的代码实现了我需要的功能,但运行起来需要很长时间(实际上,我必须在结束之前中断它)
图书馆(动物园)
#生成与我的维度相同的随机数据
my.array在前面,您正遭受R的地狱()的第二个循环:不断增长的对象。每次调用rbind
,它都会生成帧的完整副本,进行r绑定,然后覆盖原始变量名上的完整副本。因此,虽然它可能在前几十个阶段不会明显减速,但它会在100多个阶段减速。。。你做了56980次
通常最好将事情处理成一个列表
,然后在整个列表的末尾执行一次rbind
,如do.call(rbind,框架列表)
。当然,你仍然可能面临计算上的挑战,做一些可能很难的事情。。。幸运的是,zoo
几乎是窗口操作所能达到的效率,而这并不是不可能的困难
我将在一个显著减少的问题集上进行演示(因为我认为如果我们考虑16M或150万次迭代,这并不重要)
my.arrayapply()
适用于任意数量的维度,因此使用以下包装在中的.data.frame.table()
可以更快地实现相同的结果,从而有效地将数组的输出转换为数据帧:
library(zoo)
df <- as.data.frame.table(apply(my.array, c(2,3,4), rollmean, 2))
使用data.table
计算滚动平均值之前的另一个选项
library(data.table)
system.time({
ans <- setDT(as.data.frame.table(my.array))[
, .(wind=((Freq + shift(Freq)) / 2)[-1L]),
.(time=Var4, level=Var3, lat=Var2)]
cols <- c("time", "level", "lat")
ans[, (cols) := lapply(.SD, function(x) match(x, unique(x))), .SDcols=cols]
})
ans
时间:
user system elapsed
4.90 1.16 5.66
作为比较:
library(zoo)
system.time({
as.data.frame.table(apply(my.array, c(2,3,4), rollmean, 2))
})
# user system elapsed
# 21.89 0.63 22.51
永远不要迭代地构建data.frames。每次调用rbind
,它都会将整个帧复制到一个新对象中,并重写df2
。它可能会工作几十次,但是(如您所见)这是一个可怕的规模。@r2evans这是有道理的,但是…还有什么替代方案呢?一般来说,是我忘记的as.data.frame.table
,它在加速方面做得非常好(在初始测试中超过了2倍)。谢谢,我忘记了数据表的速度有多快了!我将此标记为正式答案,因为我的数据可能比我给出的示例大10倍,使用此答案将节省大量时间。我正在努力将生成的数据表转换为具有维度289 259 55 4
(类似于原来的一个)。你对此有什么提示吗?我猜它在使用数组?可能会发布另一个问题?我现在没有电脑
library(data.table)
system.time({
ans <- setDT(as.data.frame.table(my.array))[
, .(wind=((Freq + shift(Freq)) / 2)[-1L]),
.(time=Var4, level=Var3, lat=Var2)]
cols <- c("time", "level", "lat")
ans[, (cols) := lapply(.SD, function(x) match(x, unique(x))), .SDcols=cols]
})
ans
time level lat wind
1: 1 1 1 1.5
2: 1 1 1 2.5
3: 1 1 1 3.5
4: 1 1 1 4.5
5: 1 1 1 5.5
---
16467216: 4 55 259 16524195.5
16467217: 4 55 259 16524196.5
16467218: 4 55 259 16524197.5
16467219: 4 55 259 16524198.5
16467220: 4 55 259 16524199.5
user system elapsed
4.90 1.16 5.66
library(zoo)
system.time({
as.data.frame.table(apply(my.array, c(2,3,4), rollmean, 2))
})
# user system elapsed
# 21.89 0.63 22.51