【问题标题】:Cumulative sum of numeric vectors in list列表中数值向量的累积和
【发布时间】:2015-05-05 17:13:37
【问题描述】:

我希望有人能够帮助我解决这个问题。我有一个包含 48 个向量的列表对象,每个向量的长度为 2,000,000 个观察值。下面是创建相同结构的代码,每个向量只有 100,000 个项目:

mtx_sim <- matrix(data = runif(48 * 100000), ncol = 48, nrow = 100000)
mtx_list <- as.list(data.frame(mtx_sim))

我想对列表中向量的每一行进行累积求和。但是,有一个规定,我只想对最后 30 个向量求和。例如,列表中的第 35 个向量应添加到前面的 34 个向量中。另一方面,列表中的第四个向量应该添加到前面的三个向量(向量编号为三、二和一)。这是我的代码示例,它依赖于 lapply 函数结合 rowSums,速度相对较慢:

start <- c(rep(1, times = 30), seq(2, 19, 1))
end <- seq(1,48,1)

system.time(xxx <- lapply(1:48, function(x)
rowSums(
  matrix(
    unlist(mtx_list[start[x]:end[x]]), 
    ncol = (end[x] - start[x] + 1)))
) )

 user  system elapsed 
 62.19    0.56   63.04 

有人有优化代码的想法吗?

【问题讨论】:

    标签: r vector add lapply sapply


    【解决方案1】:

    你在一个合理的算法中做了两件昂贵的事情:

    1. 您正在为每次迭代从列表中重新创建一个矩阵;这可能很慢
    2. 您正在重复计算整个行的总和,而实际上您只需要计算边际变化

    这是另一种选择。我们重构原始矩阵一次,然后只添加边缘列。

    fun_brodie <- function(mtx_list) {
      mtx <- do.call(cbind, mtx_list)
      base <- mtx[, 1]
      res <- list(base)
      for(i in seq(ncol(mtx))[-1]) 
        res[[i]] <- res[[i - 1]] + mtx[, i] - if(i > 30) mtx[, i - 30] else 0
      res
    }
    res <- fun_brodie(mtx_list)
    

    确认相等:

    all.equal(res, xxx)
    # [1] TRUE
    

    基准测试:

    library(microbenchmark)
    microbenchmark(times=3, fun_marat(mtx_list), fun_brodie(mtx_list), fun_op(mtx_list))
    

    生产:

    Unit: milliseconds
                     expr        min        lq       mean
      fun_marat(mtx_list)  1661.9135  1763.418  1800.3530
     fun_brodie(mtx_list)   115.7877   116.061   153.6794
         fun_op(mtx_list) 58059.7803 60388.303 62060.5557
    

    感谢 Marat 指出我的解释错误。另外,请注意,为了使 fun_marat 兼容,我添加了一个将列表绑定到数据框的步骤。

    【讨论】:

    • @MaratTalipov,你是对的,我误解了这个问题,感谢您指出。查看更新。
    • @BrodieG 出色的解决方案。我使问题变得比它必须的要困难得多。另外,我不知道 R 不需要 { } 围绕 for 循环。
    • @user1738753,很高兴这有帮助。请注意,如果 for 后面的表达式是单行,则只能省略 {
    【解决方案2】:

    你可以使用这个解决方案:

    M <- t(apply(mtx_sim,1,cumsum))
      if (ncol(M)>30) {
      i <- 31:ncol(M)
      M[,i] <- M[,i] - M[,i-30]
    }
    M
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      • 2018-07-02
      • 2022-11-28
      • 1970-01-01
      相关资源
      最近更新 更多