【问题标题】:Calculate row sums conditional on column with 1 and 0's in a data frame in R , want the sum between consecutive 1's between 0's计算 R 中数据框中具有 1 和 0 的列的行总和,想要 0 之间的连续 1 之间的总和
【发布时间】:2019-12-15 22:34:32
【问题描述】:

输入数据框可重现示例:

onoff = c(0,1,1,1,0,0,1,1,1,0)
amount = c(0,0.5,0,0.6,0,0,0.5,0.6,0.7,0)

mockdata = data.frame(onoff, amount)

看起来像这样。

我想对 onoff 为 0 之间的 1 的行序列求和。 所以在这个例子中,我有两组和,第一组在第 2 行和第 4 行之间,第二组在第 7 行和第 9 行之间。 所以我会输出两个数字,1.1 和 1.8。

不知道该怎么做,任何帮助将不胜感激!

【问题讨论】:

  • 如果 onoff=0 那么我们可以假设数量也是 0?

标签: r sum aggregate subset subset-sum


【解决方案1】:

我们可以使用data.table中的rleid创建一个分组列,然后使用它来获取sum

library(dplyr)
library(data.table)
mockdata %>% 
   group_by(grp = rleid(onoff)) %>% 
   mutate(Sum = sum(amount) * onoff)
# A tibble: 10 x 4
# Groups:   grp [5]
#   onoff amount   grp   Sum
#   <dbl>  <dbl> <int> <dbl>
# 1     0    0       1   0  
# 2     1    0.5     2   1.1
# 3     1    0       2   1.1
# 4     1    0.6     2   1.1
# 5     0    0       3   0  
# 6     0    0       3   0  
# 7     1    0.5     4   1.8
# 8     1    0.6     4   1.8
# 9     1    0.7     4   1.8
#10     0    0       5   0  

如果我们需要汇总输出

mockdata %>% 
  group_by(grp = rleid(onoff)) %>% 
  filter(onoff == 1) %>% 
  summarise(amount = sum(amount))

【讨论】:

    【解决方案2】:
    aggregate(mockdata$amount, list(grp = c(1, cumsum(diff(mockdata$onoff) == 1))), sum)
    
          grp   x
    1       1 1.1
    2       2 1.8
    

    【讨论】:

      【解决方案3】:

      使用base R,我们可以使用rle创建分组,使用tapply计算汇总数据

      with(rle(mockdata$onoff != 1), tapply(mockdata$amount, 
                 rep(cumsum(values), lengths), sum))
      
      #  1   2   3 
      #1.1 1.8 0.0 
      

      或者我认为更接近预期输出的另一种方法是使用onoff = 1过滤行

      mockdata$row <- seq_len(nrow(mockdata))
      temp <- subset(mockdata, onoff == 1)
      tapply(temp$amount, cumsum(c(TRUE, diff(temp$row) > 1)), sum)
      
      #  1   2 
      #1.1 1.8 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-26
        • 2022-05-04
        • 1970-01-01
        • 2014-08-30
        • 2012-12-31
        相关资源
        最近更新 更多