想象这个数据集。
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:据我所知,之前在其他帖子中尚未回答过这个问题(例如,here或here)
仅执行最后一行(即,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 的解决方案更快。存在一些细微的差异,但它们仅取决于“结束日期”是否包含在计数中。
针对评论中提供的澄清进行编辑...
我们需要确定开始到结束日期范围与“目标”日期范围相交至少 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