对向量的子向量进行分组

时间:2017-09-18 10:20:55

标签: r

我正在尝试编写一个快速函数,该函数将向量v和两个位置leftright作为输入。然后,该函数应返回包含vleft的{​​{1}}的所有子向量的总和。

例如,如果rightv = c(v_1, v_2, v_3, v_4, v_5)left = 2,则包含right = 4v_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)] 向量发生很多次,我感兴趣的是我是否可以以更智能的方式对其进行编程。我觉得当前的实现是次优的,因为我需要为每个向量分配一个矩阵,我只使用上三角形。

1 个答案:

答案 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的向量上做矩阵需要多长时间,所以这里省略了。