簡體   English   中英

是什么讓rollmean比rollapply更快(代碼方式)?

[英]What makes rollmean faster than rollapply (code-wise)?

我經常發現時間序列的滾動事件(特別是手段),並且驚訝地發現rollmeanrollapply ,並且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 <- 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對象 - 這有關系嗎?)

計算滾動平均值比計算一般滾動函數更快,因為第一個更容易計算。 在計算一般滾動功能時,你必須反復計算每個窗口上的函數,由於簡單的身份,你不必為mean做這些操作:

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

你可以通過查看getAnywhere(rollmean.zoo)來了解它是如何被利用的。

如果你想要更快的滾動平均值,可以使用runmeancaTools ,它在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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM