在R中计算各组多项目非重叠周期的总天数
在R语言中计算分组内非重叠项目周期的总天数
需求说明
按Group.ID分组,统计该组所有项目周期的总天数,若不同项目的时间周期存在重叠,重叠天数仅统计一次。
示例数据框
df<- structure(list(Group.ID = c("BQNX", "BQNX", "CLXW", "CLXW", "CLXW", "CLXW", "CLXW", "CLXW", "CLXW", "CXJR", "CXJR", "CXJR", "DMM", "DMM", "DMM"), Project.ID = c(1, 2, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3), Start.Date = structure(c(19655, 19655, 19653, 19687, 19694, 19653, 19687, 19694, 19653, 19653, 19653, 19653, 19687, 19651, 19687), class = "Date"), End.Date = structure(c(19675, 19682, 19687, 19693, 19733, 19686, 19693, 19733, 19686, 19655, 19690, 19690, 19693, 19686, 19693), class = "Date"), Days = structure(c(20, 27, 34, 6, 39, 33, 6, 39, 33, 2, 37, 37, 6, 35, 6), class = "difftime", units = "days")), row.names = c(NA, 15L), class = "data.frame")
计算示例
- BQNX组:项目1和2周期重叠,合并后总天数为27天;
- CXJR组:3个项目起始日期相同,合并后总天数为37天;
- CLXW组:合并非重叠周期后总天数为79天。
期望输出
data.frame(Group.ID = c("BQNX", "CLXW", "CXJR"), Consecutive.Days = c(27,79,37) )
实现方案
可以使用dplyr配合lubridate包完成,核心逻辑是对每个分组的时间区间进行合并重叠/连续区间,再计算合并后所有区间的总天数。
步骤1:加载依赖包
library(dplyr) library(lubridate)
步骤2:数据处理代码
result <- df %>% # 按Group.ID分组 group_by(Group.ID) %>% # 组内按起始日期排序,确保区间按时间顺序处理 arrange(Start.Date, .by_group = TRUE) %>% # 标记独立的区间组:当前区间开始晚于前一个区间结束则为新组 mutate(interval_group = cumsum(Start.Date > lag(End.Date, default = first(Start.Date) - 1))) %>% # 按分组和区间组二次分组,合并重叠区间 group_by(Group.ID, interval_group) %>% summarise( merged_start = min(Start.Date), merged_end = max(End.Date), .groups = "drop_last" ) %>% # 计算所有合并后区间的总天数 summarise(Consecutive.Days = sum(as.numeric(merged_end - merged_start))) %>% # 取消分组 ungroup() # 查看结果 print(result)
代码逻辑说明
- 分组排序:先按
Group.ID分组,再对组内的Start.Date排序,保证区间按时间顺序处理; - 标记独立区间:用
cumsum生成区间组标记,当当前区间的开始日期晚于前一个区间的结束日期时,判定为新的独立区间; - 合并重叠区间:对每个独立区间组,取最早的起始日期和最晚的结束日期,合并成一个完整的非重叠区间;
- 计算总天数:对所有合并后的区间,计算每个区间的天数并求和,得到分组内的非重叠总天数。
内容的提问来源于stack exchange,提问作者Ann
相关产品推荐
相关产品推荐

