【问题标题】:group by summing consecutive rows till 0通过对连续行求和直到 0 进行分组
【发布时间】:2021-05-27 09:37:27
【问题描述】:

我有一个具有列值的数据集。 我需要连续总结并用相同的 id 标记它们,直到总和变为 0。

Value CumSum Match
   -2     -2     1
   -1     -3     1
   -1     -4     1
    4      0     1
   -1     -1     2
    2      1     2
   -1      0     2
    1      1     3
   -1      0     3
   -1     -1     4
    1      0     4
   -1     -1     5
    1      0     5
   -5     -5     6
    5      0     6
   28     28     7
    1     29     7
   -1     28     7
  -28      0     7

数据:

structure(list(Value = c(-2L, -1L, -1L, 4L, -1L, 2L, -1L, 1L, 
-1L, -1L, 1L, -1L, 1L, -5L, 5L, 28L, 1L, -1L, -28L), CumSum = c(-2L, 
-3L, -4L, 0L, -1L, 1L, 0L, 1L, 0L, -1L, 0L, -1L, 0L, -5L, 0L, 
28L, 29L, 28L, 0L), Match = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 
3L, 4L, 4L, 5L, 5L, 6L, 6L, 7L, 7L, 7L, 7L)), row.names = c(NA, 
-19L), class = "data.frame")

【问题讨论】:

  • Match 列是您的预期输出吗?

标签: r tidyverse tibble


【解决方案1】:

我们可以从 1 开始计数,并在 CumSum 中遇到 0 时递增计数。

library(dplyr)
df %>% mutate(result = lag(cumsum(CumSum == 0) + 1,default = 1)) 

#   Value CumSum Match result
#1     -2     -2     1      1
#2     -1     -3     1      1
#3     -1     -4     1      1
#4      4      0     1      1
#5     -1     -1     2      2
#6      2      1     2      2
#7     -1      0     2      2
#8      1      1     3      3
#9     -1      0     3      3
#10    -1     -1     4      4
#11     1      0     4      4
#12    -1     -1     5      5
#13     1      0     5      5
#14    -5     -5     6      6
#15     5      0     6      6
#16    28     28     7      7
#17     1     29     7      7
#18    -1     28     7      7
#19   -28      0     7      7

使用基本 R 和 data.table 逻辑相同。

library(data.table)
setDT(df)[, result := shift(cumsum(CumSum == 0) + 1,fill = 1)]

#Base R
transform(df, result = cumsum(c(1, CumSum[-nrow(df)] == 0)))

【讨论】:

    【解决方案2】:

    这是另一种选择:

    DT[, desired := {
        v <- CumSum==0
        nafill(replace(rep(NA_integer_, .N), v, seq_len(sum(v))), "nocb")
    }]
    

    数据:

    DT <- fread("Value, CumSum, Match 
    -2, -2, 1 
    -1, -3, 1 
    -1, -4, 1 
    4, 0, 1 
    -1, -1, 2 
    2, 1, 2 
    -1, 0, 2 
    1, 1, 3 
    -1, 0, 3 
    -1, -1, 4 
    1, 0, 4 
    -1, -1, 5 
    1, 0, 5 
    -5, -5, 6 
    5, 0, 6 
    28, 28, 7 
    1, 29, 7 
    -1, 28, 7 
    -28, 0, 7")
    

    【讨论】:

      【解决方案3】:

      基础r方式

      dat$Match <- with(rle(rev(cumsum(rev(dat$CumSum == 0)))), rep(max(values) +1 - values, lengths)) 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-21
        • 1970-01-01
        • 1970-01-01
        • 2013-01-29
        • 2021-12-01
        • 1970-01-01
        相关资源
        最近更新 更多