如何向量化此 sapply 调用中的循环?

dor*_*ran 4 r

我发现 R 代码中最昂贵的部分是以下sapply调用:

L <- 2000
score <- sample(1:3, L, replace = TRUE)
d <- c(0, -1, 0.5)
sapply(1:L, function(i) sum(d[1:score[i]]))
Run Code Online (Sandbox Code Playgroud)

d该调用获取从索引 1 到索引 的向量的总和score[i],循环遍历变量中的每个元素score。挑战在于该代码作为优化例程的一部分进行评估并运行很多很多次。

我正在尝试以矢量化方式执行相同的计算,但有点困难。我想我可以创建一个这样的矩阵:

d.mat <- matrix(rep(d, L), nrow = L, byrow = TRUE)
Run Code Online (Sandbox Code Playgroud)

然后以某种方式计算rowSums(d.mat)从第 1 列到score[i]row 中的列i。有谁知道有一种方法可以在不循环的情况下做到这一点?sapply我想,如果可能的话,考虑到rowSums以下基准中的相对速度,这将比 快得多:

library(microbenchmark)
microbenchmark(sapply(1:L, function(i) sum(d[1:score[i]])), 
               rowSums(d.mat),
               times = 100)
Run Code Online (Sandbox Code Playgroud)

或者也许有人看到了更好的第三种选择。

jbl*_*d94 9

索引cumsum

microbenchmark::microbenchmark(
  sapply = sapply(1:L, function(i) sum(d[1:score[i]])),
  index = cumsum(d)[score],
  check = "equal"
)
#> Unit: microseconds
#>    expr    min      lq     mean  median     uq    max neval
#>  sapply 2494.8 2698.00 3232.279 2805.35 3516.2 6868.4   100
#>   index    4.3    5.05    8.682    6.90    8.9   60.2   100
Run Code Online (Sandbox Code Playgroud)