如何在R数据框中按条件切换参考行计算日期差并标记独立事件
问题描述
在同一受试者(按ID分组)有多条日期观测记录的场景下,需完成以下操作:
- 计算每条记录日期与当前参考日期的天数差值
- 默认参考日期为组内第一条记录的日期
- 当某条记录的日期与当前参考日期差值超过28天时,将该日期设为新参考日期,以此识别独立事件
初始数据集
dfi = structure(list(ID = c(1, 1, 2, 2, 2, 2, 3, 3, 3), date_ric = c("2018-03-09", "2018-03-21", "2003-11-30", "2003-12-16", "2004-02-05", "2004-02-10", "2006-02-23", "2006-02-24", "2014-09-25")), class = "data.frame", row.names = c(NA, -9L))
数据预览:
> dfi ID date_ric 1 1 2018-03-09 2 1 2018-03-21 3 2 2003-11-30 4 2 2003-12-16 5 2 2004-02-05 6 2 2004-02-10 7 3 2006-02-23 8 3 2006-02-24 9 3 2014-09-25
期望输出数据集
需生成包含以下字段的结果:
ID_n:组内记录的序号diff.dd:当前日期与对应参考日期的天数差值keep:标记是否为新参考日期(1表示是,0表示否)
dfo = structure(list(ID = c(1, 1, 2, 2, 2, 2, 3, 3, 3), date_ric = c("2018-03-09", "2018-03-21", "2003-11-30", "2003-12-16", "2004-02-05", "2004-02-10", "2006-02-23", "2006-02-24", "2014-09-25"), ID_n = c(1, 2, 1, 2, 3, 4, 1, 2, 3), diff.dd = c(0, 12, 0, 16, 67, 5, 0, 1, 3136 ), keep = c(1, 0, 1, 0, 1, 0, 1, 0, 1)), class = "data.frame", row.names = c(NA, -9L))
结果预览:
> dfo ID date_ric ID_n diff.dd keep 1 1 2018-03-09 1 0 1 2 1 2018-03-21 2 12 0 3 2 2003-11-30 1 0 1 4 2 2003-12-16 2 16 0 5 2 2004-02-05 3 67 1 6 2 2004-02-10 4 5 0 7 3 2006-02-23 1 0 1 8 3 2006-02-24 2 1 0 9 3 2014-09-25 3 3136 1
遇到的问题
已尝试用for/while循环实现组内计数器,但无法在日期差值超过28天时自动切换新参考日期,也无法正确计算新参考日期后的差值(例如受试者2的第5条记录后续的差值计算)。
解决方案
使用dplyr结合purrr的accumulate函数实现,无需手动写循环,逻辑更清晰:
library(dplyr) library(purrr) library(lubridate) # 处理数据 df_processed <- dfi %>% # 转换字符日期为日期格式 mutate(date_ric = ymd(date_ric)) %>% group_by(ID) %>% # 生成组内序号 mutate(ID_n = row_number(), # 追踪并更新参考日期 ref_date = accumulate(date_ric, ~if_else(.y - .x > 28, .y, .x)), # 计算与当前参考日期的天数差 diff.dd = as.integer(date_ric - ref_date), # 标记是否为新参考日期 keep = as.integer(diff.dd == 0)) %>% ungroup() # 查看结果 df_processed
代码说明
- 日期格式转换:用
lubridate::ymd将字符型日期转为标准日期格式,支持差值计算 - 组内序号生成:
row_number()直接生成组内记录的序号ID_n - 参考日期追踪:
accumulate函数逐个遍历组内日期,当当前日期与前一个参考日期差值超过28天时,自动更新参考日期为当前日期,否则保持原参考日期 - 差值计算:直接用当前日期减去参考日期,转为整数得到天数差
diff.dd - 参考点标记:当
diff.dd为0时,说明该日期是新参考日期,标记keep=1,否则为0
运行后结果与期望输出完全一致。
内容的提问来源于stack exchange,提问作者Francesca
相关产品推荐
相关产品推荐

