#r #data.table #compare #rolling-computation
#r #data.table #Сравнить #скользящее вычисление
Вопрос:
У меня есть data.table DT
с 3 столбцами, Zeit
, Spuer
и Eingriff
.
DT <- data.table(Zeit = c(1, 2, 3, 4, 5, 6, 7, 8, 9),
Spuer = c(45, 45, 32, 25, 30, 44, 34, 42, 44),
Eingriff = c(0, 0, 1, 0, 0, 0, 1, 0, 0))
Я хочу выяснить, является ли Eingriff == 1
и одним из следующих 3 значений Spuer < 30
. Если это TRUE, то Eingriff == 1
else Eingriff == 0
. Для моих реальных данных я проверяю, являются ли следующие 20 или более значений Spuer
меньше 30, поэтому такое решение, как lead (Spuer, 1), lead (Spuer, 2) и т. Д., Не является хорошим решением.
Я уже пытался реализовать решение с frollapply
помощью and shift
, но не смог заставить его работать.
В итоге результат должен выглядеть следующим образом:
res <- data.table(Zeit = c(1, 2, 3, 4, 5, 6, 7, 8, 9),
Spuer = c(45, 45, 32, 25, 30, 44, 34, 42, 44),
Eingriff = c(0, 0, 1, 0, 0, 0, 0, 0, 0))
Ответ №1:
Вот один из вариантов, использующий sapply
:
Сначала мы выясняем индексы, где Eingriff == 1
и для каждого из этих индексов проверяем, является ли any
значение в window
меньше 30.
library(data.table)
window <- 3
inds <- which(DT$Eingriff == 1)
DT[inds, Eingriff := as.integer(sapply(inds, function(x)
any(DT$Spuer[x:(x window - 1)] < 30)))]
DT
# Zeit Spuer Eingriff
#1: 1 45 0
#2: 2 45 0
#3: 3 32 1
#4: 4 25 0
#5: 5 30 0
#6: 6 44 0
#7: 7 34 0
#8: 8 42 0
#9: 9 44 0
Ответ №2:
Вот еще один вариант, использующий неравнозначное соединение:
k <- 3L
DT[, c("start", "end") := .(.I, .I k)]
DT[Eingriff==1L, Eingriff :=
DT[.SD, on=.(start>start, start<=end), by=.EACHI, any(x.Spuer < 30)]$V1
]
вывод:
Zeit Spuer Eingriff start end
1: 1 45 0 1 4
2: 2 45 0 2 5
3: 3 32 1 3 6
4: 4 25 0 4 7
5: 5 30 0 5 8
6: 6 44 0 6 9
7: 7 34 0 7 10
8: 8 42 0 8 11
9: 9 44 0 9 12