【发布时间】:2017-03-13 21:45:45
【问题描述】:
我想对 R 中的向量执行指数加权移动平均(参数化定义为 here)。有没有比我下面的第一次尝试更好的实现?
我的第一次尝试是:
ewma <- function(x, a) {
n <- length(x)
s <- rep(NA,n)
s[1] <- x[1]
if (n > 1) {
for (i in 2:n) {
s[i] <- a * x[i] + (1 - a) * s[i-1]
}
}
return(s)
}
y <- 1:1e7
system.time(s <- ewma(y,0.5))
#user system elapsed
# 2.48 0.00 2.50
在我的第二次尝试中,我认为通过矢量化可以做得更好:
ewma_vectorized <- function(x,a) {
a <- 0.1
n <- length(x)
w <- cumprod(c(1, rep(1-a, n-1)))
x1_contribution <- w * x[1]
w <- a * w
x <- x[-1]
s <- apply(as.array(1:(n-1)), 1, function(i,x,w){sum(w[i:1] * x[1:i])}, x=x, w=w)
s <- x1_contribution + c(0,s)
return(s)
}
system.time(s <- ewma_vectorized(y,0.5))
# I stopped the program after it continued to run for 4min
我想我不应该对第二次尝试的结果感到太惊讶。这是一个非常丑陋的矢量化尝试。但是必须有一些类似的东西在我的第一次尝试中有所改进......对吗?
更新:
我确实找到了更好的实现 here 并对其进行了如下调整:
ewma_vectorized_v2 <- function(x, a) {
s1 <- x[1]
sk <- s1
s <- vapply(x[-1], function(x) sk <<- (1 - a) * x + a * sk, 0)
s <- c(s1, s)
return(s)
}
system.time(s <- ewma_vectorized_v2(y,0.5))
# user system elapsed
# 1.74 0.01 1.76
【问题讨论】:
-
您只是想使用快速实现吗? The TTR package implements it in C.
-
我试图在 R 中执行此操作并避免使用任何包。但这是一个有用的链接。
-
@Gregor:这是一个可怕的包。 :P OP 可以改用
stats::filter。 -
@JoshuaUlrich 哈!在那个问题上,我当然会听从你的。我承认我没用过,只是关注了Gabor's link here。