data.table 中后续值或先前值的滚动计算

rolling computation for following or previous values in a data.table

我有一个包含 3 列的 data.table DTZeitSpuerEingriff

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 == 1Spuer < 30 的后 3 个值之一。如果为真,则 Eingriff == 1 否则 Eingriff == 0。对于我的真实数据,我检查 Spuer 中接下来的 20 个或更多值是否小于 30,因此 lead(Spuer, 1)、lead(Spuer, 2) 等解决方案不是一个好的解决方案。

我已经尝试使用 frollapplyshift 实现解决方案,但无法实现。

最后的结果应该是这样的:

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

这是一个使用 sapply 的选项:

我们首先找出 Eingriff == 1 所在的索引,并针对每个索引检查 window 中值的 any 是否小于 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

这是另一个使用 non-equi 连接的选项:

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