【问题标题】:Adding numeric vectors of unequal length in a list together with an offset based on the index?在列表中添加长度不等的数字向量以及基于索引的偏移量?
【发布时间】:2020-03-23 02:57:32
【问题描述】:

我有一个向量列表,如下所示:

list_num <- list(c(1,1,1,1,1), c(2,2), c(5), c(3,3,3,3,3))

我想将所有这些向量加在一起,但将每个向量偏移它在列表中的位置值。即 - 当添加第二个向量 c(2,2) 时,我们将它添加到第二个位置,然后是第一个。所以本质上,它看起来像下面这样,所有元素都加在一起

list_num <- list(c(1,1,1,1,1), c(0,2,2), c(0,0,5), c(0,0,0,3,3,3,3,3))

# Output:
>> 1 3 8 4 4 3 3 3

我目前的方法包括生成一个向量来容纳添加的结果并遍历每个元素以添加它:

# Find the length for each of the vectors in the list
list_len <- unlist(lapply(list_num, function(x) { return(length(x))}))

# Find how long will the vector to add the results have to be
list_len <- 1:length(list_num)+list_len

# Generate a vector to house the added results
list_len <- rep(0, max(list_len)-1) 

# Then iterate over each of the elements by index i 
for(i in 1:length(list_num)){

  # Add the vector at position i to the subset of our aggregated vector
  list_len[i:(i+length(list_num[[i]])-1)] <- list_len[i:(i+length(list_num[[i]])-1)] + list_num[[i]]
}

print(list_len)
>> 1 3 8 4 4 3 3 3

但我认为这是相当低效的;我正在寻找一种更有效的方法来聚合这些向量。

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用lapply 来添加使用rep 的偏移量0

    out <- lapply(seq_along(list_num), function(n) c(rep(0, n-1), list_num[[n]]))
    out
    
    #[[1]]
    #[1] 1 1 1 1 1
    
    #[[2]]
    #[1] 0 2 2
    
    #[[3]]
    #[1] 0 0 5
    
    #[[4]]
    #[1] 0 0 0 3 3 3 3 3
    

    然后我们可以添加NA 以使长度相等并计算逐行总和。

    rowSums(sapply(out, `[`, 1:max(lengths(out))), na.rm = TRUE)
    #[1] 1 3 8 4 4 3 3 3
    

    【讨论】:

    • 谢谢!这是朝着正确方向迈出的一步——但它不包括如何将它们加在一起,这仍然需要遍历每个元素。
    • 我错过了那部分。我已经更新了答案以包含它。
    • 感谢您这样做!不过,我进行了几次测试,虽然比我当前的解决方案要简洁得多,但它似乎要慢得多,可能是由于添加了前导零(我打算包括该步骤来说明计算的样子)。跨度>
    【解决方案2】:

    用 C++ 编写这个要求似乎并不难,因此这里有一个使用 Rcpp 的选项:

    library(Rcpp)
    cppFunction("NumericVector psumUnevenList(List a, int len) {
        NumericVector res(len), v;
    
        for (int i=0; i<a.length(); i++) {
            v = a[i];
            for (int j=0; j<v.length(); j++) {
                res[i+j] += v[j];
            }
        }
    
        return res;
    }")
    maxn <- max(seq_along(list_num) - 1L + lengths(list_num))
    psumUnevenList(list_num, maxn)
    #[1] 1 3 8 4 4 3 3 3
    

    【讨论】:

      【解决方案3】:

      Base R 解决方案(两步):

      # Store a scalar valued at the length of longest vector in the list: 
      vec_list_max_length <- max(lengths(vec_list))
      
      # Set the length of each vector to be equal to the maximum length, rowbind the list
      # together and get the sum of each row: 
      rowSums(sapply(vec_list, function(x) {
        length(x) = vec_list_max_length
        return(replace(x, is.na(x), 0))
      }))
      

      数据:

      vec_list <- list(c(1,1,1,1,1), c(0,2,2), c(0,0,5), c(0,0,0,3,3,3,3,3))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        • 1970-01-01
        • 2014-07-03
        • 2013-05-02
        • 2011-07-25
        相关资源
        最近更新 更多