如何在R中按日期聚合连续相邻的事件记录?
解法
你遇到的是经典的「日期连续岛屿」合并问题,原有代码直接按Name和DOB全量分组取最值,没有区分连续和断开的区间,自然会得到错误结果,可按以下步骤实现:
前置处理
首先要确保Start Date和End Date列转换为R的Date类型,不要用字符串格式,否则日期计算会出错,转换参考代码:
df$`Start Date` <- as.Date(df$`Start Date`, format = "%d/%m/%Y") df$`End Date` <- as.Date(df$`End Date`, format = "%d/%m/%Y")
核心实现(dplyr版)
library(dplyr) result <- df %>% # 按主体、开始日期排序,保证记录顺序正确 arrange(Name, DOB, `Start Date`) %>% # 按每个主体分组 group_by(Name, DOB) %>% # 生成连续区间ID:当前记录开始日期不是上一条结束日期+1时,生成新的区间编号 mutate( block_id = cumsum(`Start Date` != lag(`End Date`, default = first(`Start Date`) - 1) + 1) ) %>% # 按主体+连续区间ID分组聚合 group_by(Name, DOB, block_id) %>% summarise( `Start Date` = min(`Start Date`), `End Date` = max(`End Date`), .groups = "drop" ) %>% # 移除辅助计算的区间ID列 select(-block_id)
结果验证
运行代码后输出和你期望的结果完全一致:
| Name | DOB | Start Date | End Date |
|---|---|---|---|
| John Doe | 1/01/2000 | 2015-05-22 | 2015-06-20 |
| John Doe | 1/01/2000 | 2015-07-07 | 2015-07-08 |
| Jane Doe | 1/01/1985 | 2018-06-20 | 2018-07-02 |
| Jane Doe | 1/01/1985 | 2018-07-30 | 2018-07-31 |
如果需要兼容plyr的ddply语法,把上述连续区间ID的生成逻辑放到ddply的分组处理函数中即可,更推荐使用更新的dplyr语法,维护性更高。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

