如何识别开始到结束日期范围与“目标”日期范围相交的情况

问题描述 投票:0回答:1

想象这个数据集。

library(tidyverse)
library(lubridate)

df <- data.frame(
  ID = 1:10,
  start_date_smoking = c("28/06/2011", "27/07/2012", "09/04/2003", "01/07/2013", "28/06/2011",
                         "01/09/2013", "01/09/2013", "30/08/2014", "01/09/2013", "01/09/2013"),
  end_date_smoking = c("01/01/2017", "01/01/2017", "01/01/2017", "01/01/2017", "01/09/2013",
                       "01/09/2013", "02/09/2013", "01/01/2017", "31/08/2014", "31/08/2014")
)

df <- df %>% 
  mutate(
    start_date_smoking =dmy(start_date_smoking),
    end_date_smoking =  dmy(end_date_smoking),
    days = time_length(difftime(end_date_smoking, start_date_smoking),"days"))
  )

如何捕获在 2013 年 9 月 1 日至 2014 年 8 月 31 日期间吸烟且吸烟时间至少 180 天的吸烟者/病例 (ID)。我尝试了 filter() 但无法让它工作。例如,我想捕获在 2013 年 1 月 9 日之前开始吸烟的人(例如 ID 1),因为他们在这两个日期之间吸烟。但是,我不想捕获在 2014 年 8 月 30 日开始吸烟的人(例如,ID 8),即使他们吸烟了几年,因为在 2013 年 9 月 1 日和 31 日内,他不会在 180 天内吸烟。 -08-2014 时间表。

最终,我希望它返回一个过滤为 ID 1、2、3、4、9 和 10 的 df。

我尝试这样做,但它没有过滤到我期望的行

start_range <- dmy("01/09/2013")
end_range <- dmy("31/08/2014")

df %>%
  filter(days >= 180 &
         (start_date_smoking >= start_range & start_date_smoking <= end_range) |
           (end_date_smoking >= start_range & end_date_smoking <= end_range) |
           (start_date_smoking <= start_range & end_date_smoking >= end_range))

编辑1:据我所知,之前在其他帖子中尚未回答过这个问题(例如,herehere

仅执行最后一行(即,filter(start_date_smoking <= start_range & end_date_smoking >= end_range))的问题是代码无法识别它正在过滤的情况。例如,如果某人的开始日期是 1985-01-01,而 end_date 是 2014 -05-15。从技术上讲,他们在“2013-09-01”和结束日期 2014-05-15 之间吸烟了 180 天(即 255 天),但同样,如果他们的开始日期是1986-12-01 和 end_date 是 2014-02-25,因为他们在“2013-09-01”和 end_date 2014-02-25 之间只吸烟了 177 天。

编辑 2:非常感谢杰克和本。尽管我有一个很大的数据集(超过 1500 万行),但它们都可以工作,因此 Ben 的解决方案更快。存在一些细微的差异,但它们仅取决于“结束日期”是否包含在计数中。

r dplyr lubridate
1个回答
1
投票

针对评论中提供的澄清进行编辑...

我们需要确定开始到结束日期范围与“目标”日期范围相交至少 180 天的情况。

target.date.range <- seq(as.Date("2013-09-01"), as.Date("2014-08-31"), by = "days")

for (i in 1:nrow(df)){
  seq.days <- seq(df$start_date_smoking[i], df$end_date_smoking[i], by = "days")
  
  df$days.in.range[i] <- length(intersect(seq.days, target.date.range)) 
}

df %>% filter(days.in.range >= 180)

返回:

 ID start_date_smoking end_date_smoking  days days.in.range
1  1         2011-06-28       2017-01-01  2014           365
2  2         2012-07-27       2017-01-01  1619           365
3  3         2003-04-09       2017-01-01  5016           365
4  4         2013-07-01       2017-01-01  1280           365
5  9         2013-09-01       2014-08-31   364           365
6 10         2013-09-01       2014-08-31   364           365
© www.soinside.com 2019 - 2024. All rights reserved.