通过将连续行相加直到 0 进行分组

group by summing consecutive rows till 0

我有一个包含列值的数据集。 我需要连续总结这个并用相同的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")

我们可以从 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)))

这是另一个选项:

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")

基础 r 方式

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