我正在尝试加速/向量化时间序列中的一些计算。我可以在一个for循环中向量化一个可以依赖于早期迭代结果的计算吗?例如:
z <- c(1,1,0,0,0,0)
zi <- 2:6
for (i in zi) {z[i] <- ifelse (z[i-1]== 1, 1, 0) }
使用在前面的步骤中更新的ZI值:
> z
[1] 1 1 1 1 1 1
在我将其向量化的过程中
z <- c(1,1,0,0,0,0)
z[zi] <- ifelse( z[zi-1] == 1, 1, 0)
逐元素操作不使用在操作中更新的结果:
> z
[1] 1 1 1 0 0 0
因此,这种向量化操作是以“并行”而不是迭代的方式进行的。有没有一种方法可以让我编写/向量化它来获得for循环的结果?
发布于 2011-08-23 05:35:20
ifelse
是矢量化的,如果你在for循环中一次只在一个元素上使用它,会有一些损失。在您的示例中,您可以通过使用if
而不是ifelse
获得相当好的加速比。
fun1 <- function(z) {
for(i in 2:NROW(z)) {
z[i] <- ifelse(z[i-1]==1, 1, 0)
}
z
}
fun2 <- function(z) {
for(i in 2:NROW(z)) {
z[i] <- if(z[i-1]==1) 1 else 0
}
z
}
z <- c(1,1,0,0,0,0)
identical(fun1(z),fun2(z))
# [1] TRUE
system.time(replicate(10000, fun1(z)))
# user system elapsed
# 1.13 0.00 1.32
system.time(replicate(10000, fun2(z)))
# user system elapsed
# 0.27 0.00 0.26
您可以通过编译fun2
获得一些额外的速度提升。
library(compiler)
cfun2 <- cmpfun(fun2)
system.time(replicate(10000, cfun2(z)))
# user system elapsed
# 0.11 0.00 0.11
因此,在没有矢量化的情况下,速度提高了10倍。正如其他人所说(有些人已经说明了),有一些方法可以向量化您的示例,但这可能不会转化为您的实际问题。希望这是通用的,可以应用。
如果您知道如何用自回归过程或移动平均过程来表示问题,那么filter
函数可能对您也很有用。
发布于 2011-08-23 06:39:17
有时你只需要以完全不同的方式思考它。你要做的是创建一个向量,如果它是1或0,那么每一项都与第一项相同。
z <- c(1,1,0,0,0,0)
if (z[1] != 1) z[1] <- 0
z[2:length(z)] <- z[1]
发布于 2018-05-28 17:41:14
有一个函数可以完成这个特殊的计算:cumprod
(累积乘积)
> cumprod(z[zi])
[1] 1 0 0 0 0
> cumprod(c(1,2,3,4,0,5))
[1] 1 2 6 24 0 0
否则,使用Rccp进行矢量化,如其他答案所示。
https://stackoverflow.com/questions/7153586
复制相似问题