#r #tidyverse #tibble
#r #tidyverse #tibble
Вопрос:
У меня есть набор данных, который имеет значение столбца. Мне нужно последовательно суммировать это и помечать их одним и тем же идентификатором, пока сумма не станет 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. Является
Match
ли столбец вашим ожидаемым результатом?
Ответ №1:
Мы можем начать подсчет с 1 и увеличивать его всякий раз, когда встречается 0 CumSum
.
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))