我经常发现时间序列(尤其是均值)的滚动变化,并惊讶地发现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 <- 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)
来了解如何利用它。如果您想要更快的滚动平均值,请使用
runmean
中的caTools
,它是用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