如何在R中检查日期是否在时间间隔列表内?

4

我有两个数据框(tibbles),每个数据框有两个变量:

  • df.POS:ID(ID变量);DATE(阳性实验室检测日期)
  • df.NEG:ID(ID变量);data(阴性实验室检测日期列表,包含多个检测结果)。

请注意,data是一个列表变量,使用tidyr包的nest()函数创建。

library(tidyverse)
library(lubridate)

# negative tests
dates.neg <- ymd(c('2018-02-01', '2018-02-06', '2018-02-10', 
             '2018-02-21', '2018-04-05'))
df.NEG <- tibble(ID = paste0('ID_', rep(1, 5)),
          DATE = dates.neg) %>%
       group_by(ID) %>% 
          nest()
df.NEG

## # A tibble: 1 x 2
##   ID    data            
##   <chr> <list>          
## 1 ID_1  <tibble [5 × 1]>


dates.pos <- ymd(c('2018-02-07', '2018-02-12', '2018-02-13', 
             '2018-02-20', '2018-02-21', '2018-03-18'))

df.POS <- tibble(ID = paste0('ID_', rep(1, 6)),
           DATE = dates.pos)
df.POS

## # A tibble: 6 x 2
##   ID    DATE      
##   <chr> <date>    
## 1 ID_1  2018-02-07
## 2 ID_1  2018-02-12
## 3 ID_1  2018-02-13
## 4 ID_1  2018-02-20
## 5 ID_1  2018-02-21
## 6 ID_1  2018-03-18

我想查找在阳性测试结果后2天内,哪些阳性测试结果也有阴性测试结果。我尝试使用了purrr包的map2()函数。

df.TOTAL <- df.POS %>%
  left_join(df.NEG, by = 'ID') %>%
    mutate(TIME = interval(DATE, DATE + days(2)),
           RESULT = map2(data, "DATE", TIME, ~ .x %within% .y)) 

很不幸,我的代码无法运行。在进行完阳性检测后的2天内,若测试结果为阴性,则RESULT变量应该是逻辑型且返回TRUE。但实际上它是一个列表,返回NULL。

df.TOTAL

## # A tibble: 6 x 5
##   ID    DATE       data             TIME                           RESULT
##   <chr> <date>     <list>           <S4: Interval>                 <list>
## 1 ID_1  2018-02-07 <tibble [5 × 1]> 2018-02-07 UTC--2018-02-09 UTC <NULL>
## 2 ID_1  2018-02-12 <tibble [5 × 1]> 2018-02-12 UTC--2018-02-14 UTC <NULL>
## 3 ID_1  2018-02-13 <tibble [5 × 1]> 2018-02-13 UTC--2018-02-15 UTC <NULL>
## 4 ID_1  2018-02-20 <tibble [5 × 1]> 2018-02-20 UTC--2018-02-22 UTC <NULL>
## 5 ID_1  2018-02-21 <tibble [5 × 1]> 2018-02-21 UTC--2018-02-23 UTC <NULL>
## 6 ID_1  2018-03-18 <tibble [5 × 1]> 2018-03-18 UTC--2018-03-20 UTC <NULL>

能有人帮忙吗?

我需要一些帮助,非常感谢您的提前帮助!

1个回答

3

首先,需要注意的是可以通过以下方式测试来自“负”日期向量的任何元素是否在“正”时间间隔内:

any(dates.neg %within% interval(dates.pos[1], dates.pos[1] + days(2)))
# [1] FALSE

这表明可以使用map2或更有用的map2_lgl来采用以下方法:
df.TOTAL <- df.POS %>%
  left_join(df.NEG, by = 'ID') %>%
    mutate(TIME = interval(DATE, DATE + days(2)),
           RESULT = map2_lgl(data, TIME, ~any(.x$DATE %within% .y)))
# # A tibble: 6 x 5
#   ID    DATE       data             TIME                           RESULT
#   <chr> <date>     <list>           <S4: Interval>                 <lgl> 
# 1 ID_1  2018-02-07 <tibble [5 x 1]> 2018-02-07 UTC--2018-02-09 UTC FALSE 
# 2 ID_1  2018-02-12 <tibble [5 x 1]> 2018-02-12 UTC--2018-02-14 UTC FALSE 
# 3 ID_1  2018-02-13 <tibble [5 x 1]> 2018-02-13 UTC--2018-02-15 UTC FALSE 
# 4 ID_1  2018-02-20 <tibble [5 x 1]> 2018-02-20 UTC--2018-02-22 UTC TRUE  
# 5 ID_1  2018-02-21 <tibble [5 x 1]> 2018-02-21 UTC--2018-02-23 UTC TRUE  
# 6 ID_1  2018-03-18 <tibble [5 x 1]> 2018-03-18 UTC--2018-03-20 UTC FALSE 

感谢 @ubuntu 改进答案。

map2_lgl(data, TIME, ~ any(.x$DATE %within% y)) 不是更加自解释吗?无论如何 - 很棒的答案,感谢您提供宝贵的信息。 - utubun
@utubun:啊,没错——这样更直接。我会编辑以反映您的建议。 - Weihuang Wong
非常感谢。太棒了! :-) - Norbert Köhler
@NorbertKöhler:欢迎来到SO,很高兴能帮到你。如果这个答案解决了你的问题,请标记为已接受。 - Weihuang Wong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接