基于ID列与3天内滞后日期对Data Frame分组的技术需求
解决方案:按ID分组并基于日期间隔划分子组
问题说明
需要对数据集按id分组,将每个id组内相邻日期间隔≤3天的记录归为同一子组,最终生成全局唯一的group编号。
原始数据集
id <- c("123", "123", "123", "123", "123", "456", "456") date <- as.Date(c("2022/10/01", "2022/10/04","2022/10/07", "2022/12/01", "2022/12/04", "2022/03/01", "2022/06/09")) x <- data.frame(id, date)
实现代码(使用dplyr包)
library(dplyr) # 定义日期间隔阈值(示例为3天) threshold <- 3 result <- x %>% # 按id分组,确保每组内日期有序 group_by(id) %>% arrange(date, .by_group = TRUE) %>% # 计算当前日期与前一日期的差值,首次记录差值设为NA mutate(date_diff = date - lag(date)) %>% # 标记是否需要新建子组:差值>阈值或为首次记录 mutate(new_group = is.na(date_diff) | date_diff > threshold) %>% # 生成组内的子组编号 mutate(group_in_id = cumsum(new_group)) %>% ungroup() %>% # 将组内子组转换为全局唯一的group编号 mutate(group = dense_rank(paste(id, group_in_id, sep = "_"))) %>% # 保留需要的列 select(id, date, group) print(result)
输出结果
| id | date | group |
|---|---|---|
| 123 | 2022-10-01 | 1 |
| 123 | 2022-10-04 | 1 |
| 123 | 2022-10-07 | 1 |
| 123 | 2022-12-01 | 2 |
| 123 | 2022-12-04 | 2 |
| 456 | 2022-03-01 | 3 |
| 456 | 2022-06-09 | 4 |
代码说明
- 分组与排序:先按
id分组,同时对每组内的date排序,确保日期顺序正确。 - 计算日期差:用
lag(date)获取前一条记录的日期,计算差值。 - 标记新组:当日期差超过阈值或为组内第一条记录时,标记为新组起点。
- 生成组内编号:用
cumsum(new_group)累加标记,得到每个id内的子组编号。 - 全局编号转换:通过
dense_rank将id+组内编号的组合转换为全局唯一的group编号。
内容的提问来源于stack exchange,提问作者Melissa Salazar
相关产品推荐
相关产品推荐

