группировать путем суммирования последовательных строк до 0

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