#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