在R中基于日期差与重置逻辑按唯一ID划分独立事件
问题描述
我在R中有一个数据框df,每个个体对应多个事件,每个事件由唯一日期定义。diff_earliest_date列是对应唯一id的最早日期与后续日期之间的天数。
原始数据
data <- data.frame( id = c(1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 5678, 5678, 5678, 5678, 5678, 5678), date = as.Date(c("1997-04-08", "1997-04-12", "1997-04-19", "1997-09-01", "1997-09-14", "1997-10-22", "1997-12-10", "1998-06-16", "1998-06-27", "1998-06-29", "1998-09-13", "1998-09-25", "1999-05-17", "1999-07-18", "1997-04-08", "1997-04-22", "1997-09-14", "1997-10-25", "1998-05-13", "1998-10-07")), event = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6), diff_earliest_date = c("0 days", "4 days", "11 days", "146 days", "159 days", "197 days", "246 days", "434 days", "445 days", "447 days", "523 days", "535 days", "769 days", "831 days", "0 days", "10 days", "159 days", "200 days", "400 days", "547 days"))
原始数据预览:
> data id date event diff_earliest_date 1 1234 1997-04-08 1 0 days 2 1234 1997-04-12 2 4 days 3 1234 1997-04-19 3 11 days 4 1234 1997-09-01 4 146 days 5 1234 1997-09-14 5 159 days 6 1234 1997-10-22 6 197 days 7 1234 1997-12-10 7 246 days 8 1234 1998-06-16 8 434 days 9 1234 1998-06-27 9 445 days 10 1234 1998-06-29 10 447 days 11 1234 1998-09-13 11 523 days 12 1234 1998-09-25 12 535 days 13 1234 1999-05-17 13 769 days 14 1234 1999-07-18 14 831 days 15 5678 1997-04-08 1 0 days 16 5678 1997-04-22 2 10 days 17 5678 1997-09-14 3 159 days 18 5678 1997-10-25 4 200 days 19 5678 1998-05-13 5 400 days 20 5678 1998-10-07 6 547 days
需求说明
为每个id定义间隔243天的唯一事件:当某个日期与对应id的最早日期间隔>243天时,重置天数差以标记新的唯一事件。最终数据需新增diff_reset和unique_event列,预期结果如下:
> data id date event diff_earliest_date diff_reset unique_event 1 1234 1997-04-08 1 0 days 0 days 1 2 1234 1997-04-12 2 4 days 4 days 1 3 1234 1997-04-19 3 11 days 11 days 1 4 1234 1997-09-01 4 146 days 146 days 1 5 1234 1997-09-14 5 159 days 159 days 1 6 1234 1997-10-22 6 197 days 197 days 1 7 1234 1997-12-10 7 246 days 0 days 2 8 1234 1998-06-16 8 434 days 189 days 2 9 1234 1998-06-27 9 445 days 200 days 2 10 1234 1998-06-29 10 447 days 202 days 2 11 1234 1998-09-13 11 523 days 0 days 3 12 1234 1998-09-25 12 535 days 13 days 3 13 1234 1999-05-17 13 769 days 0 days 4 14 1234 1999-07-18 14 831 days 63 days 4 15 5678 1997-04-08 1 0 days 0 days 1 16 5678 1997-04-22 2 10 days 10 days 1 17 5678 1997-09-14 3 159 days 159 days 1 18 5678 1997-10-25 4 200 days 0 days 1 19 5678 1998-05-13 5 400 days 200 days 2 20 5678 1998-10-07 6 547 days 0 days 3
我尝试用dplyr的mutate结合日期运算和lag(date)实现,但未成功,觉得可能需要循环遍历数据,恳请提供解决方案。
解决方案
无需使用循环,用dplyr的分组累积计算即可实现需求,完整步骤如下:
1. 转换天数列为数值型
先把字符格式的diff_earliest_date转为整数天数,方便后续计算:
library(dplyr) data <- data %>% group_by(id) %>% mutate(diff_num = as.numeric(gsub(" days", "", diff_earliest_date))) %>% ungroup()
2. 计算唯一事件组unique_event
通过天数与243的整除关系,划分每个事件所属的唯一组:
data <- data %>% group_by(id) %>% mutate(unique_event = floor(diff_num / 243) + 1) %>% ungroup()
3. 计算重置后的天数差diff_reset
以每个唯一事件组的最早日期为起点,计算当前日期与起点的天数差:
data <- data %>% group_by(id, unique_event) %>% mutate(diff_reset = paste(date - min(date), "days")) %>% ungroup() %>% # 调整列顺序并移除中间变量 select(id, date, event, diff_earliest_date, diff_reset, unique_event)
完整可运行代码
library(dplyr) # 原始数据 data <- data.frame( id = c(1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 5678, 5678, 5678, 5678, 5678, 5678), date = as.Date(c("1997-04-08", "1997-04-12", "1997-04-19", "1997-09-01", "1997-09-14", "1997-10-22", "1997-12-10", "1998-06-16", "1998-06-27", "1998-06-29", "1998-09-13", "1998-09-25", "1999-05-17", "1999-07-18", "1997-04-08", "1997-04-22", "1997-09-14", "1997-10-25", "1998-05-13", "1998-10-07")), event = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6), diff_earliest_date = c("0 days", "4 days", "11 days", "146 days", "159 days", "197 days", "246 days", "434 days", "445 days", "447 days", "523 days", "535 days", "769 days", "831 days", "0 days", "10 days", "159 days", "200 days", "400 days", "547 days")) # 转换天数列为数值型 data <- data %>% group_by(id) %>% mutate(diff_num = as.numeric(gsub(" days", "", diff_earliest_date))) %>% ungroup() # 计算唯一事件组 data <- data %>% group_by(id) %>% mutate(unique_event = floor(diff_num / 243) + 1) %>% ungroup() # 计算重置后的天数差 data <- data %>% group_by(id, unique_event) %>% mutate(diff_reset = paste(date - min(date), "days")) %>% ungroup() %>% select(id, date, event, diff_earliest_date, diff_reset, unique_event) # 查看结果 print(data)
运行上述代码后,输出结果与预期完全一致。
内容的提问来源于stack exchange,提问作者Nao
相关产品推荐
相关产品推荐

