我正拼命避免for循环来计算自定义的财务指标(多只股票,每只股票5000行)。我正在尝试使用purrr::map2,在对现有向量进行数学计算时,这是很好的,但是我需要引用我试图创建的向量的滞后(以前)值。在不引用前一个值的情况下,purrr::map2可以正常工作:
some_function <- function(a, b) { (a * b) + ((1 - a) * b) }
a <- c(0.019, 0.026, 0.012, 0.022) # some indicator
b <- c(15.5, 16.7, 14.8, 13.1) # close price
purrr::map2(a, b, some_function),这只会导致原来的闭包值。
15.5, 16.7, 14.8, 13.1但我真正想做的是创建一个新的向量(c),作为计算的一部分,回顾它本身(滞后)。如果是第一行,则为c == b,否则:
desired_function <- function(a, b, c) { (a * b) + ((1 - a) * lag(c)) } 因此,我创建了一个向量c并填充并尝试:
c <- c(15.5, 0, 0, 0)
purrr::map2(a, b, c, desired_function)得到所有的空值,很明显。
C的值应该是:15.50, 15.53, 15.52, 15.47
引用以前的值是指示器中常见的事情,它迫使我使用笨拙、缓慢的“for循环”。如有任何建议,将不胜感激。
发布于 2022-07-03 15:01:14
如果在向量中计算某个值需要来自同一个向量的另一个值,那么它就不能被向量化;您必须一个接一个地计算它们。
For循环本身并不慢,而是如何使用它们。例如,从数据帧中一次检索一个值,或者一次插入一个值,这是一种非常慢的常见做法。
在过去的10年里,R中的for-循环的实现有了很大的改进,它们以前效率很低,在旧的帖子中,你会发现很多人都在抱怨它。
建议阅读:
https://www.r-bloggers.com/2018/06/why-loops-are-slow-in-r/
这两个老问题(嗯,他们的答案):
Speed up the loop operation in R
一个小小的实验
让我们对最简单的(最愚蠢的?)进行基准测试。函数的purrr::map()的for -循环实现:c = a*b + (1-a) * b
在这个包含1000万项的基准测试中,for-循环的速度是purrr::map2()的15倍以上。
# functions ---------------------------------------------------------------
desired_function <- function(a,b) { a*b + (1-a) * b }
des_fnc_for <- function(a, b) {
c <- numeric(length(a))
c[1] <- b[1]
for(i in seq_along(a)) c[i] <- a[i] * b[i] + (1 - a[i]) * b[i]
return(c)
}
# verify --------------------------------------------------------------------
a <- c(0.019, 0.026, 0.012, 0.022) # some indicator
b <- c(15.5, 16.7, 14.8, 13.1) # close price
unlist(purrr::map2(a,b,desired_function))
[1] 15.5 16.7 14.8 13.1
des_fnc_for(a,b)
[1] 15.5 16.7 14.8 13.1
# benchmark ---------------------------------------------------------------
a <- runif(10000000, 0.01, 0.03)
b <- runif(10000000, 13, 17)
system.time( des_fnc_for(a,b) )
user system elapsed
1.143 0.007 1.163
system.time( purrr::map2(a,b,desired_function) )
user system elapsed
18.570 0.627 19.761 发布于 2022-07-03 15:31:13
这里有一些解决方案,第一种是使用stats::lag (使用stats::,因为dplyr包总是掩蔽lag!),
r <- numeric(4L)
for (i in 1:4) {
r[i] <- c[i + 1] <- a[i]*b[i] + (1 - a[i])*stats::lag(c)[i]
}
r
# [1] 15.50000 15.53120 15.52243 15.46913另一个使用的是在每次迭代中更新的起始值,大约快20%。
r <- numeric(4L)
sval <- 15.5
for (i in 1:4) {
r[i] <- sval <- a[i]*b[i] + (1 - a[i])*sval
}
r
# [1] 15.50000 15.53120 15.52243 15.46913数据:
a <- c(0.019, 0.026, 0.012, 0.022)
b <- c(15.5, 16.7, 14.8, 13.1)
c <- c(15.5, 0, 0, 0)https://stackoverflow.com/questions/72842980
复制相似问题