如何使用 data.table 和 lubridate 检查多个日期是否在一个区间内?

How to check if several dates lie within a interval using data.table and lubridate?

我有一个 data.table 有几列日期, 和定义间隔的两列。 我想检查是否有任何日期在该间隔内。

这是一个只有三列日期的玩具示例。

DT <- data.table(d1=dmy(c("1-1-2019", "2-2-2019")), 
    d2=dmy(c("1-3-2019", "2-2-2022")), 
    d3=dmy(c("1-1-2020", "2-2-2021")),
    initial=dmy(c("1-1-2020","5-5-2022")), 
    final=dmy(c("1-3-2020","1-1-2023")))

         d1         d2         d3    initial      final
 2019-01-01 2019-03-01 2020-01-01 2020-01-01 2020-03-01
 2019-02-02 2022-02-02 2021-02-02 2022-05-05 2023-01-01

我可以这样做:(它也可以用于过滤而不是创建新列)

DT[,new:=(d1 >= initial & d1 <= final) | (d2 >= initial & d2 <= final) | 
   (d3 >= initial & d3 <= final)]

但是这很长,特别是如果我有超过三列的话。

我试过这个精简版

DT[,any( c(d1,d2,d3 ) %within% interval(initial, final))]

但是好像不行。

最简单的方法是什么?
也欢迎使用其他软件包的任何解决方案

它没有矢量化。所以,我们可以使用 group by 和 rows

DT[, new := any( c(d1,d2,d3 ) %within% interval(initial, final)),
      by = 1:nrow(DT)]

-输出

DT
#           d1         d2         d3    initial      final   new
#1: 2019-01-01 2019-03-01 2020-01-01 2020-01-01 2020-03-01  TRUE
#2: 2019-02-02 2022-02-02 2021-02-02 2022-05-05 2023-01-01 FALSE

或向量化函数

DT[, new := Reduce(`|`, lapply(.SD, function(x) x >= initial & 
    x <= final)),.SDcols = patterns('^d\d+$')]
DT
#          d1         d2         d3    initial      final   new
#1: 2019-01-01 2019-03-01 2020-01-01 2020-01-01 2020-03-01  TRUE
#2: 2019-02-02 2022-02-02 2021-02-02 2022-05-05 2023-01-01 FALSE

备选方案:

DT[, new := rowSums(sapply(.SD, between, initial, final)) > 0,
   .SDcols = c("d1", "d2", "d3")]
DT
#            d1         d2         d3    initial      final    new
#        <Date>     <Date>     <Date>     <Date>     <Date> <lgcl>
# 1: 2019-01-01 2019-03-01 2020-01-01 2020-01-01 2020-03-01   TRUE
# 2: 2019-02-02 2022-02-02 2021-02-02 2022-05-05 2023-01-01  FALSE

确保你使用的是 data.table::between ...如果你在 dplyr::betweendplyr::between 之间有冲突,后者会抱怨(因为它要求它的 lower/upper 边界是长度-1).

这个答案既是向量化的,又是任意列数的高效答案。也就是说,它会在每个 (向量化)中调用一次 between,而无论列数如何,它只会调用一次 rowSums。 (此外,rowSums(.) 通常比 apply(., 1, any) 或类似的规范 R 方法更快。)