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