R-таблица данных - расчет для каждой строки, используя все строки перед текущей строкой
Я хочу рассчитать разные вещи по id и по порядку (время).
Например, с помощью:
dt = data.table( id=c(1,1,1,2,2,2,3,3,3), hour=c(1,5,5,6,7,8,23,23,23), ip=c(1,1,45,2,2,2,3,1,1), target=c(1,0,0,1,1,1,1,1,0), day=c(1,1,1,1,1,1,3,2,1))
id hour ip target day
1: 1 1 1 1 1
2: 1 5 1 0 1
3: 1 5 45 0 1
4: 2 6 2 1 1
5: 2 7 2 1 1
6: 2 8 2 1 1
7: 3 23 3 1 3
8: 3 23 1 1 2
9: 3 23 1 0 1
Я хочу подсчитать для каждого идентификатора количество активных дней и активных часов для каждой строки.
Это означает, что я хочу получить следующий результат:
id hour ip target day nb_active_hours_so_far
1: 1 1 1 1 1 0 (first occurence of id when ordered by hour)
2: 1 5 1 0 1 1 (has been active in hour "1")
3: 1 5 45 0 1 2 (has been active in hour "1" and "5")
4: 2 6 2 1 1 0 (first occurence)
5: 2 7 2 1 1 1 (has been active in hour "6")
6: 2 8 2 1 1 2 (has been active in hour "6" and "7")
7: 3 23 3 1 3 0 (first occurence)
8: 3 23 1 1 2 1 (has been active in hour "23")
9: 3 23 1 0 1 1 (has been active in hour "23" only)
Чтобы получить общее количество активных часов, я бы сделал:
dt[, nb_active_hours := length(unique(hour)), by=id]
но я хочу иметь и до сих пор. Я не знаю, как это сделать...
Любая помощь будет оценена.
Ответы
Ответ 1
Кажется, что это работает (хотя в разных случаях он не тестировался)
dt[, nb_active_hours_so_far := cumsum(c(0:1, diff(hour[-.N]))>0), by = id]
# id hour ip target day temp nb_active_hours_so_far
# 1: 1 1 1 1 1 0 0
# 2: 1 5 1 0 1 1 1
# 3: 1 5 45 0 1 1 2
# 4: 2 6 2 1 1 0 0
# 5: 2 7 2 1 1 1 1
# 6: 2 8 2 1 1 2 2
# 7: 3 23 3 1 3 0 0
# 8: 3 23 1 1 2 0 1
# 9: 3 23 1 0 1 0 1
Ответ 2
Yerk. У меня есть это уродливое решение:
library(data.table)
dt[ ,nb_active_hours_so_far:=c(0,head(cumsum(c(1,diff(hour)>0)), -1)),id][]
# id hour ip target day nb_active_hours_so_far
#1: 1 1 1 1 1 0
#2: 1 5 1 0 1 1
#3: 1 5 45 0 1 2
#4: 2 6 2 1 1 0
#5: 2 7 2 1 1 1
#6: 2 8 2 1 1 2
#7: 3 23 3 1 3 0
#8: 3 23 1 1 2 1
#9: 3 23 1 0 1 1
Ответ 3
Или вы можете использовать функции rleid/shift
из версии devel data.table
, т.е. v1.9.5
. Инструкции по установке версии devel here
. (Спасибо @Frank за shift
)
library(data.table)
dt[,nb_active_hours_so_far := shift(rleid(hour),fill=0L), id]
# id hour ip target day nb_active_hours_so_far
#1: 1 1 1 1 1 0
#2: 1 5 1 0 1 1
#3: 1 5 45 0 1 2
#4: 2 6 2 1 1 0
#5: 2 7 2 1 1 1
#6: 2 8 2 1 1 2
#7: 3 23 3 1 3 0
#8: 3 23 1 1 2 1
#9: 3 23 1 0 1 1