我正在尝试编写一个快速函数,该函数将向量v
和两个位置left
和right
作为输入。然后,该函数应返回包含v
和left
的{{1}}的所有子向量的总和。
例如,如果right
和v = c(v_1, v_2, v_3, v_4, v_5)
,left = 2
,则包含right = 4
和v_2
的子向量是:
v_4
特别是,这些集合始终包含c(v_1, v_2, v_3, v_4)
c(v_1, v_2, v_3, v_4, v_5)
c(v_2, v_3, v_4)
c(v_2, v_3, v_4, v_5)
。最后,我想要一个提供
v_2, v_3, v_4
我目前的解决方案是将S(v, 2, 4) = c(sum(v[1:4]), sum(v[1:5]), sum(v[2:4]), sum(v[2:5]))
变为上三角矩阵:
v
还有更有效的方法可以创建比较here的矩阵。
然后
set.seed(1)
v <- rnorm(1:5)
vmat <- matrix(0, 5, 5)
for(i in 1:nrow(vmat)) for(j in i:nrow(vmat)) vmat[i,j] <- sum(v[i:j])
给出正确的总和。
由于此操作必须针对不同的Smat <-function(vmat, left, right) vmat[1:left, right:nrow(vmat)]
向量发生很多次,我感兴趣的是我是否可以以更智能的方式对其进行编程。我觉得当前的实现是次优的,因为我需要为每个向量分配一个矩阵,我只使用上三角形。
答案 0 :(得分:1)
这个怎么样?
subvector_sum <- function(v, start, end){
v_list <- c(
lapply(1:start,
FUN = function(i, end) i:end,
end),
lapply(end:length(v),
FUN = function(i, start) start:i,
start)
)
v_list <- c(unique(v_list), list(seq_along(v)))
vapply(v_list, function(index) sum(v[index]), numeric(1))
}
set.seed(1)
v <- rnorm(5)
subvector_sum(v, 2, 4)
为了比较,以下是在长度为5,100和1000的向量上运行时两种方法的基准。
library(microbenchmark)
subvector_matrix <- function(v, left, right){
vmat <- matrix(0, length(v), length(v))
for(i in 1:nrow(vmat)) for(j in i:nrow(vmat)) vmat[i,j] <- sum(v[i:j])
vmat[1:left, right:nrow(vmat)]
}
set.seed(1)
v5 <- rnorm(5)
v100 <- rnorm(100)
v1000 <- rnorm(1000)
microbenchmark(
apply5 = subvector_sum(v5, 2, 4),
matrix5 = subvector_matrix(v5, 2, 4),
apply100 = subvector_sum(v100, 2, 4),
matrix100 = subvector_matrix(v100, 2, 4),
apply1000 = subvector_sum(v1000, 2, 4)
)
Unit: microseconds
expr min lq mean median uq max neval
apply5 21.700 26.5390 43.54169 30.938 60.2630 84.456 100
matrix5 29.618 38.1225 47.03129 46.480 55.1310 73.312 100
apply100 229.026 255.1260 274.39212 273.600 292.5145 351.018 100
matrix100 10273.639 10596.3570 11894.37717 10850.604 13593.2015 15193.747 100
apply1000 5371.710 5520.0945 6305.76903 5663.346 5886.3600 13557.719 100
正如您所看到的,我建议的apply
方法在长度为1000的向量上比在长度为100的向量上的矩阵方法上运行得更快。我不想等到看看在长度为1000的向量上做矩阵需要多长时间,所以这里省略了。