Условная совокупная сумма, основанная на статусе объекта

#r #data.table #iteration #cumsum

#r #данные.таблица #итерация #cumsum

Вопрос:

Я ищу условную совокупную сумму, основанную на статусе объекта. Я хотел бы суммировать все предыдущие строки, когда статистика «Новая», но сбросить совокупную сумму, когда статус становится «Старым». Я также хочу повторить это по идентификаторам групп.

Таким образом, в примере ниже:

 set.seed(5)
df <- data.table(ID=c(rep("A",10),rep("B",10)),time=c(seq(1,10),seq(1,10)),
                 Status=sample(c("New","Old"),20,replace = TRUE))
df
    ID time Status
 1:  A    1    Old
 2:  A    2    New
 3:  A    3    New
 4:  A    4    New
 5:  A    5    New
 6:  A    6    New
 7:  A    7    New
 8:  A    8    New
 9:  A    9    Old
10:  A   10    New
11:  B    1    New
12:  B    2    New
13:  B    3    New
14:  B    4    Old
15:  B    5    Old
16:  B    6    New
17:  B    7    New
18:  B    8    Old
19:  B    9    Old
20:  B   10    Old
 

Желаемый результат:

     ID time Status Cond_Sum
 1:  A    1    Old        0
 2:  A    2    New        1
 3:  A    3    New        2
 4:  A    4    New        3
 5:  A    5    New        4
 6:  A    6    New        5
 7:  A    7    New        6
 8:  A    8    New        7
 9:  A    9    Old        0
10:  A   10    New        1
11:  B    1    New        1
12:  B    2    New        2
13:  B    3    New        3
14:  B    4    Old        0
15:  B    5    Old        0
16:  B    6    New        1
17:  B    7    New        2
18:  B    8    Old        0
19:  B    9    Old        0
20:  B   10    Old        0
 

Предпочтительным является решение data.table.

Заранее большое спасибо.

Ответ №1:

Мы можем создать столбец группировки с rleid «идентификатором», «Статусом», затем указать выражение условия в i ( Status == "New" ), присвоить последовательность строк ( seq_len(.N) ) «Cond_Sum», сгруппированных по «grp» (или использовать rowid(grp) )

 library(data.table)
df[, grp := rleid(ID, Status)]
df[, Cond_Sum := 0][Status == 'New', 
          Cond_Sum := seq_len(.N), grp][, grp := NULL][]
 

-вывод

 #     ID time Status Cond_Sum
# 1:  A    1    Old        0
# 2:  A    2    New        1
# 3:  A    3    New        2
# 4:  A    4    New        3
# 5:  A    5    New        4
# 6:  A    6    New        5
# 7:  A    7    New        6
# 8:  A    8    New        7
# 9:  A    9    Old        0
#10:  A   10    New        1
#11:  B    1    New        1
#12:  B    2    New        2
#13:  B    3    New        3
#14:  B    4    Old        0
#15:  B    5    Old        0
#16:  B    6    New        1
#17:  B    7    New        2
#18:  B    8    Old        0
#19:  B    9    Old        0
#20:  B   10    Old        0