【问题标题】:What makes rollmean faster than rollapply (code-wise)?是什么让 rollmean 比 rollapply 更快(代码方面)?
【发布时间】:2013-08-07 20:36:30
【问题描述】:

我经常发现时间序列的滚动事物(特别是意味着),并且惊讶地发现 rollmean 明显快于 rollapply,并且 align = 'right' 方法比 rollmeanr 包装器快。

他们是如何实现这一速度的?为什么在使用rollmeanr() 包装器时会丢失一些?

一些背景知识:我一直在使用rollapplyr(x, n, function(X) mean(X)),但是我最近偶然发现了一些使用rollmean 的示例。文件建议rollapplyr(x, n, mean)(注意没有function 部分的论点)使用rollmean,所以我认为性能不会有太大差异,但是rbenchmark 揭示了显着的差异。

require(zoo)
require(rbenchmark)

x <- rnorm(1e4)
r1 <- function() rollapplyr(x, 3, mean) # uses rollmean
r2 <- function() rollapplyr(x, 3, function(x) mean(x))
r3 <- function() rollmean(x, 3, na.pad = TRUE, align = 'right')
r4 <- function() rollmeanr(x, 3, align = "right")

bb <- benchmark(r1(), r2(), r3(), r4(), 
          columns = c('test', 'elapsed', 'relative'), 
          replications = 100, 
          order = 'elapsed')

print(bb)

我惊讶地发现rollmean(x, n, align = 'right') 明显更快——比我的rollapply(x, n, function(X) mean(X)) 方法快约40 倍。

  test elapsed relative
3 r3()    0.74    1.000
4 r4()    0.86    1.162
1 r1()    0.98    1.324
2 r2()   27.53   37.203

随着数据集大小的增加,差异似乎越来越大。我在上面的代码中只更改了x(到rnorm(1e5))的大小,然后重新运行测试,函数之间的差异更大。

  test elapsed relative
3 r3()   13.33    1.000
4 r4()   17.43    1.308
1 r1()   19.83    1.488
2 r2()  279.47   20.965 

对于x &lt;- rnorm(1e6)

  test elapsed relative
3 r3()   44.23    1.000
4 r4()   54.30    1.228
1 r1()   65.30    1.476
2 r2() 2473.35   55.920

他们是怎么做到的?另外,这是最佳解决方案吗?当然,这很快,但有没有更快的方法来做到这一点?

(注意:通常我的时间序列几乎总是xts 对象——这有关系吗?)

【问题讨论】:

  • 您可能想从caTools 尝试runmean 以获得更快的结果
  • @DWIN 我确实阅读了帮助页面。我看到了你在?rollapplyr 中引用的文字,但它没有解释原因。接下来我去了?rollmean,发现“这些函数分别计算滚动平均值、最大值和中值,因此类似于‘rollapply’,但针对速度进行了优化”……这也没有解释原因。此外,两者都没有解释为什么rollmean(x, n, align = 'right')rollmeanr(x, n) 快。最后,这些都不能解释为什么性能差距会随着数据的大小而扩大。
  • @DWin -- 这是一个代码交换,所以我希望答案是 XYZ 已经完成以加快 rollmean 的速度,rollmean(x, n, align = 'right')rollmeanr 快一些好原因,并且由于其他一些有趣原因,性能差距会随着任务规模的增长而扩大。这个地方不是来帮助人们学习的吗?
  • 首先,我建议通过getAnywhere("rollmean.zoo")getAnywhere("rollapply.zoo") 来看看这些功能。
  • 如果有人不知道 OP 的意思,因为他说的是“为什么”而不是“如何”,我会感到非常惊讶

标签: r zoo


【解决方案1】:

计算滚动平均值比计算一般滚动函数更快,因为第一个更容易计算。在计算一般滚动函数时,您必须一次又一次地计算每个窗口上的函数,而 mean 不必这样做,因为它很简单:

 (a2 + a3 + ... + an)/(n-1) = (a1 + a2 + ... + a(n-1))/(n-1) + (an - a1)/(n-1)

您可以通过查看 getAnywhere(rollmean.zoo) 来了解它是如何利用的。

如果您想要更快的滚动平均值,请使用 caTools 中的 runmean,它是在 C 中实现的,使其更快(它也可以更好地扩展,因此随着数据大小的增加会变得更快)。

library(microbenchmark)
library(caTools)
library(zoo)

x = rnorm(1e4)
microbenchmark(runmean(x, 3, endrule = 'trim', align = 'right'),
               rollmean(x, 3, align = 'right'))
#Unit: microseconds
#                                             expr      min        lq     median        uq       max neval
# runmean(x, 3, endrule = "trim", align = "right")  631.061  740.0775   847.5915  1020.048  1652.109   100
#                  rollmean(x, 3, align = "right") 7308.947 9155.7155 10627.0210 12760.439 16919.092   100

【讨论】:

  • 还有TTR::runMean,它适用于xts对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
  • 2012-02-14
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
  • 2020-08-12
相关资源
最近更新 更多