【发布时间】:2019-11-20 21:27:14
【问题描述】:
问题
我正在寻找 R 中 for 循环的更快替代方案。具体来说,可以提供由于加法而导致矢量减少的中间结果。 purrr::accumulate() 可以解决问题,但似乎很慢。下面显示了一个可重现的示例。
功能
带有for循环
accumulate_values <- function(time_vector,
input_vector,
list_of_parameters)
{
number_samples <- length(time_vector)
time_steps <- c(0, diff(time_vector))
calculation <- (list_of_parameters$K * input_vector - list_of_parameters$M) * time_steps
accumulated_values <- rep(0, number_samples)
for (i in 2:number_samples) {
accumulated_values[i] <- max(0, accumulated_values[i-1] + calculation[i])
}
return(accumulated_values)
}
使用 purrr::accumulate()
功能
library(tidyverse)
accumulate_values_purrr <- function(time_vector,
input_vector,
list_of_parameters)
{
number_samples <- length(time_vector)
time_steps <- c(0, diff(time_vector))
calculation <- (list_of_parameters$K * input_vector - list_of_parameters$M) * time_steps
# accumulated_values <- rep(0, number_samples)
# for (i in 2:number_samples) {
# accumulated_values[i] <- max(0, accumulated_values[i-1] + calculation[i])
#
# }
accumulated_values <- calculation %>% purrr::accumulate(function(x, y) max(0, x + y))
return(accumulated_values)
}
结果
# Data
Nums <- 1000000
my_time_vector <- seq(1, Nums, by = 1)
my_input_vector <- rnorm(Nums)
my_list_of_parameters <- list(K = 5, M = 0.01)
# Results
set.seed(1987)
library(tictoc)
# With for-loop
tic()
answer1 <- accumulate_values(my_time_vector,
my_input_vector,
my_list_of_parameters)
toc()
## 1.73 sec elapsed
# With purrr::accumulate
tic()
answer2 <- accumulate_values_purrr(my_time_vector,
my_input_vector,
my_list_of_parameters)
toc()
## 5.93 sec elapsed
identical(answer1, answer2)
## [1] TRUE
问题
如何让accumulate() 更快?有更快的替代方案吗?
【问题讨论】:
-
你能用
Reduce(function(x, y) max(0, x + y), calculation, accumulate = TRUE)试试还是用cummax(calculation) -
@akrun 感谢您的评论。
Reduce()在这些数据上比purrr::accumulate()快,但仍然比for-loop慢。cummax()不提供相同的结果。 -
可能你需要
cummax(pmax(0, calculation)) -
不,
cummax(pmax(0, calculation))提供的结果不同。 -
使用 c++
std::accumulate和Rcpp包:adv-r.had.co.nz/Rcpp.html