【问题标题】:Sum elements of a vector beween zeros in R在R中的零之间求和向量的元素
【发布时间】:2019-01-28 12:40:06
【问题描述】:

我有一个带有零和正数的向量。我只想将 介于 零之间的数字相加。

一个简单的例子:

x <- c(0,0,0,0,0,1,23,24,54,12,1,23,0,0,0,0,1,23,56,76,0,1,13)

也就是说,我想对元素 1,23,24,54,12,1,231,23,56,761,13 求和。

因此,我想要的输出是: 13815614

我发现了这个非常相似的问题,但它是在 Python 上的: Sum elements of a list between zeros in Python

谢谢。

【问题讨论】:

    标签: r vector sum


    【解决方案1】:

    不是很紧凑,但也可以。使用whichdiff 定位x 中值从非零变为零的位置。使用该信息对相关子向量求和。

    z <- which(x!=0)[diff(which(x!=0))>1] # 12 20
    z <- c(1, z, length(x))+1 # 2 13 21 24
    for(i in 1:(length(z)-1)){ print(sum(x[z[i]:z[i+1]], na.rm=T)) }
    
    [1] 138
    [1] 156
    [1] 14
    

    【讨论】:

    • sapply(1:(length(z)-1), function(i) sum(x[z[i]:z[i+1]], na.rm=TRUE)) 得到向量结果
    【解决方案2】:

    这是data.table的解决方案:

    library("data.table")
    x <- c(0,0,0,0,0,1,23,24,54,12,1,23,0,0,0,0,1,23,56,76,0,1,13)
    s <- tapply(x, rleidv(x==0), sum)
    s[s!=0]
    # > s[s!=0]
    #   2   4   6 
    # 138 156  14 
    

    【讨论】:

      【解决方案3】:

      我们可以使用tapply,用cumsum创建群组,并获取每个群组的sum

      new_x <- tapply(x, cumsum(x == 0), sum)
      new_x
      
      #  1   2   3   4   5   6   7   8   9  10 
      #  0   0   0   0 138   0   0   0 156  14 
      

      由于所有数字都是正数,我们可以忽略 0 并过滤值大于 0 的数字。

      new_x[new_x > 0]
      #  5   9  10 
      #138 156  14 
      

      我们也可以用sapplysplit遵循同样的逻辑

      sapply(split(x, cumsum(x==0)), sum)
      

      【讨论】:

      • 这种拆分方法看起来很奇怪。我敢打赌rle 可以用来更好地拆分它(不过我没有时间这样做)
      • @Sotos 你说的奇怪是什么意思?它实际上给了我与tapply 相同的输出
      • 不不,输出是正确的。分裂的方式很奇怪。 ([0], [0], [0], ... [0, 23, ...])...而我的意思是 rle 可以像 [0, 0, 0, 0, 0], [1, 23, 24, ...]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 2011-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-22
      相关资源
      最近更新 更多