【发布时间】:2021-07-07 00:13:17
【问题描述】:
我有以下代码,属于 2 个时间序列。 maxNo 是时间序列中的元素数。 longStopPrev 是 longStop 的 1 位滞后版本。变量在循环之前启动,因此它们的大小不会在每次迭代中增加。当 maxNo 很大时,这个循环需要很长时间才能运行。
有什么聪明的方法可以避免使用 for 循环和矢量化,或者让它运行得更快吗?
我认为主要的挑战是变量longStopPrev 在循环的每次运行中都有可能被更改,这使得仅作为向量运行一次操作变得困难。但是可能有更好的执行方式,类似于不同的搜索算法。
我已经使用foreach 进行了测试,但它只会让代码运行得更慢。我还测试了 for 循环内的更改
longStopPrev = stats::lag(longStop, k=1,na.pad = TRUE) # lag 1
与:
longStopPrev[i+1] <- longStop[i]
但结果稍微慢了一点。
我试图在下面制作一个可重现的示例。我在我的时间序列中使用 ~10.000 点测试代码,并且实际上希望以 ~100.000 或更长的时间运行。
require("xts")
set.seed(47); n = 1e1;
data <- xts(rnorm(n)+10,
order.by = seq(as.POSIXct("2017-05-31 17:00:00"), length=n, by="min"))
diff=0.5
longStop = data - diff
longStopPrev = stats::lag(longStop, k=1,na.pad = TRUE) # lag 1
longStopPrev = na.approx(longStopPrev, rule=2,na.rm = FALSE,maxgap=1) # fill NA values by approx
maxNo <- nrow(longStop)
for(i in 1:maxNo) {
if(as.numeric(data[i])>as.numeric(longStopPrev[i]) ){
longStop[i] <- max(longStop[i],longStopPrev[i])
longStopPrev = stats::lag(longStop, k=1,na.pad = TRUE) # lag 1
}
}
longStopPrev = na.approx(longStopPrev, rule=2,na.rm = FALSE,maxgap=1) # fill NA values by approx
【问题讨论】:
-
首先,在进入循环之前执行
longStop <- numeric(maxNo)- 这样您就不会动态增加向量大小,这很昂贵。 -
如果你做了一个可重现的例子,回答这个问题会更容易。
-
与其要求我们下载导入一些数据文件,不如让您的示例在问题中独立。要么提供代码来模拟一些示例数据,使用内置数据集,要么与
dput(your_data[1:10, ])共享几行数据副本/粘贴。 -
在某些情况下,是的。在没有看到示例数据的情况下,我很难真正了解您的代码的作用。我认为可以使用矢量化
pmax或cummax或其他东西来代替循环 - 一个 10 行的示例非常适合理解正在发生的事情并尝试简化。 -
对于增量改进(或获得整体效果),是的,在大数据上进行测试很好,但这是共享几行代码来模拟示例数据的一个很好的用例。某些东西,
set.seed(47); n = 1e5; longStop = rnorm(n)比 Google 驱动器链接更易于分享。对于回答者来说,它的进入门槛较低,它很稳定,使问题成为更好的长期资源,因为数据不会在任何时候消失,如果需要真正测试限制,我们可以将n调整得更高。跨度>
标签: r performance for-loop time-series vectorization