R语言数据处理:按规则生成latest_discharge_date列提取最大后续日期
问题:生成符合规则的
latest_discharge_date列 样本数据
data <- data.frame( year = c(2018, 2018, 2018, 2018, 2018, 2018, 2018, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020), patient_id = c(101, 102, 103, 104, 102, 102, 106, 105, 105, 107, 108, 109, 105, 105, 201, 202, 203, 204, 205, 205, 205, 209, 208), discharge_date = as.Date(c("1/1/2018", "1/5/2018", "1/8/2018", "2/5/2018", "2/10/2018", "2/11/2018", "3/1/2018", "1/2/2019", "1/10/2019", "3/1/2019", "3/5/2019", "3/25/2019", "5/5/2019", "5/6/2019", "1/1/2020", "2/1/2020", "2/10/2020", "3/3/2020", "4/1/2020", "4/2/2020", "4/3/2020", "6/17/2020", "8/8/2020"), format = "%m/%d/%Y"), contagious_admission = c(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0) )
需求说明
需要创建latest_discharge_date列,取值规则如下:
- 若当前行的
patient_id与后续行的patient_id不同,则取当前行的discharge_date; - 若当前行与后续行的
patient_id相同,且两行的contagious_admission均为0,则取当前行的discharge_date; - 若同一
patient_id存在连续的后续行,且该系列首行的contagious_admission为0,后续行的contagious_admission为1,则首行的latest_discharge_date需取这些后续行中的最大discharge_date。
第一次尝试及问题
data |> mutate( latest_discharge_date = case_when( contagious_admission == 0 & lead(contagious_admission) == 0 ~ discharge_date, contagious_admission == 0 & lead(contagious_admission) == 1 ~ lead(discharge_date) , TRUE ~ NA) )
该代码在多数情况下正常运行,但针对patient_id = 205,其contagious_admission == 0的行对应的latest_discharge_date取了"2020-04-02",而实际需要取该患者后续contagious_admission == 1组中的最大日期"2020-04-03"。
第二次尝试及问题
data |> mutate( latest_discharge_date = case_when( contagious_admission == 0 & lead(contagious_admission) == 0 ~ discharge_date, contagious_admission == 0 & lead(contagious_admission) == 1 ~ lead(pmax(lead(discharge_date))) , TRUE ~ NA) )
该代码能正确处理多个后续contagious_admission == 1的行,但会在单个后续行的场景下出现错误。
解决方案
要解决这个问题,我们可以按patient_id分组,标记每个0值行对应的后续1值行组,再提取组内最大日期。具体代码如下:
library(dplyr) library(tidyr) data_processed <- data |> group_by(patient_id) |> # 标记当前0值行是否紧跟1值行 mutate( is_leading_zero = contagious_admission == 0 & lead(contagious_admission, default = 0) == 1, # 将前置0行和后续1值行归为同一组 group_id = ifelse(is_leading_zero, row_number(), NA), group_id = fill(group_id, .direction = "down") ) |> # 计算每个组内1值行的最大出院日期 mutate(max_contagious_date = ifelse(!is.na(group_id), max(discharge_date[contagious_admission == 1]), NA)) |> # 按规则生成目标列 mutate( latest_discharge_date = case_when( # 规则1:当前是患者最后一行 row_number() == n() ~ discharge_date, # 规则3:前置0行取对应1值组的最大日期 is_leading_zero ~ max_contagious_date, # 规则2:当前和后续都是0,取当前日期 contagious_admission == 0 & lead(contagious_admission) == 0 ~ discharge_date, # 1值行设为NA(可按需调整) TRUE ~ NA ) ) |> # 清理临时列 select(-is_leading_zero, -group_id, -max_contagious_date) |> ungroup() print(data_processed)
代码说明
- 分组处理:按
patient_id分组,确保仅处理同一患者的行; - 标记关联组:用
fill将前置0行的标记向下传递,把它和后续的1值行绑定为同一组; - 计算组内最大值:针对每个关联组,提取其中1值行的最大出院日期;
- 规则匹配赋值:严格对应三条需求规则赋值,覆盖所有场景。
运行后,patient_id=205的0值行将正确取到2020-04-03,单个后续1值行的场景也能正常工作。
内容的提问来源于stack exchange,提问作者Mahm00d27
相关产品推荐
相关产品推荐

