R语言长格式数据集如何判断日期是否落在两次检测间隔内
问题背景
现有两个患者相关数据集:
tests:长格式存储的检测日期与检测结果数据,每位患者对应2条不同检测日期的记录meds:存储患者的用药日期
示例数据如下:
(tests <- structure(list(id = c(1, 1, 2, 2, 3, 3), test_date = structure(c(10957, 10963, 11001, 11035, 11091, 11230), class = "Date"), test_result = c(1, 1, 0, 1, 0, 0)), row.names = c(NA, -6L), class = "data.frame")) #> id test_date test_result #> 1 1 2000-01-01 1 #> 2 1 2000-01-07 1 #> 3 2 2000-02-14 0 #> 4 2 2000-03-19 1 #> 5 3 2000-05-14 0 #> 6 3 2000-09-30 0 (meds <- structure(list(id = c(1, 2, 3), med_date = structure(c(10959, 10956, NA), class = "Date")), row.names = c(NA, -3L), class = "data.frame")) #> id med_date #> 1 1 2000-01-03 #> 2 2 1999-12-31 #> 3 3 <NA>
需求为在tests数据集中新增一列,标记对应患者是否在两次检测的日期间隔内接受了药物治疗,预期输出如下:
#> id test_date test_result received_med_within #> 1 1 2000-01-01 1 TRUE #> 2 1 2000-01-07 1 TRUE #> 3 2 2000-02-14 0 FALSE #> 4 2 2000-03-19 1 FALSE #> 5 3 2000-05-14 0 FALSE #> 6 3 2000-09-30 0 FALSE
最初设想的实现流程为:
- 将
tests数据集通过pivoting转换为宽格式 - 通过
left_join将meds数据集关联到宽表 - 使用
if_else(med_date %within% interval(test_date_1, test_date_2), TRUE, FALSE)逻辑判断用药日期是否在检测间隔内 - 再将数据集转换回长格式
但该方案流程繁琐,真实场景下数据集包含更多字段时,长宽表转换操作复杂度较高,需要找到可直接在长格式数据集上完成日期区间判断的简洁方法。
实现方案
不需要做长宽表转换,直接按患者分组计算检测日期区间即可,基于dplyr的实现代码如下:
library(dplyr) result <- tests %>% # 按患者ID分组,直接计算当前患者的检测时间区间端点 group_by(id) %>% mutate( first_test = min(test_date), last_test = max(test_date) ) %>% ungroup() %>% # 关联对应患者的用药日期 left_join(meds, by = "id") %>% # 区间判断,用药日期非空且落在两次检测之间则返回TRUE mutate( received_med_within = !is.na(med_date) & med_date > first_test & med_date < last_test, # 删除中间计算用的辅助列 first_test = NULL, last_test = NULL )
运行代码得到的结果和预期输出完全一致。
该方法全程在长表结构下操作,不会受数据集其他字段的影响,逻辑简单易维护。如果后续场景扩展为患者存在多次检测记录,该逻辑依然有效:默认判断用药时间是否落在该患者最早、最晚检测日期的区间内;如果需要判断用药是否落在相邻两次检测的区间,只需在分组后对检测日期排序,用lag()/lead()函数取相邻日期构造区间即可,灵活度远高于长宽表转换的方案。
注:如果需要包含区间端点(即用药日期等于检测日期也算在间隔内),只要把判断条件里的
>/<替换为>=/<=即可。
内容的提问来源于stack exchange,提问作者Andrea M
相关产品推荐
相关产品推荐

