6

私は定期的に時系列 (特に手段) のローリングを見つけてrollmeanおり、 が よりも著しく高速でrollapplyあり、align = 'right'メソッドがrollmeanrラッパーよりも高速であることに驚きました。

彼らはどのようにしてこのスピードアップを達成したのでしょうか? rollmeanr()そして、ラッパーを使用すると、なぜ一部が失われるのでしょうか?

いくつかの背景: 私は を使用していrollapplyr(x, n, function(X) mean(X))ましたが、最近、 を使用したいくつかの例に出くわしましたrollmean。ドキュメントは(議論rollapplyr(x, n, mean)の一部がないことに注意してください)使用を示唆しているため、パフォーマンスに大きな違いがあるとは思いませんでしたが、顕著な違いが明らかになりました。functionrollmeanrbenchmark

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上記のコードで(to )のサイズのみを変更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オブジェクトです。これは問題ですか?)

4

1 に答える 1

7

ローリング平均の計算は、一般的なローリング関数の計算よりも高速です。一般的なローリング関数を計算するときは、各ウィンドウで関数を何度も計算する必要がありますmean

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

を見ると、それがどのように活用されているかがわかりますgetAnywhere(rollmean.zoo)

さらに高速なローリング平均が必要な場合は、runmeanfromcaToolsを使用します。これは 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
于 2013-08-07T21:49:57.327 に答える