使用dplyr按条件处理行:实现患者随访数据单条记录聚合
问题
现有患者随访数据框df:
| ID | FOLLOW-UP | RECURRENCE | RECURRENCE DATE |
|---|---|---|---|
| 15 | 1 | no | |
| 15 | 2 | yes | 2003-05-15 |
| 16 | 1 | no | |
| 29 | 1 | yes | 2002-06-10 |
| 29 | 2 | yes | 2002-12-16 |
| 34 | 1 | yes | 2009-11-15 |
| 34 | 2 | no | |
| 34 | 3 | yes | 2012-05-03 |
| 36 | 1 | no | |
| 36 | 2 | no |
字段说明:
- ID:患者标识
- FOLLOW-UP:随访次数
- RECURRENCE:复发情况(yes/no)
- RECURRENCE DATE:复发日期(仅复发时填写)
需要将每个患者仅保留一条记录,规则如下:
- 若患者多次复发,保留**最早复发(首次复发日期)**的行;
- 若患者既有复发又有未复发记录,保留最早复发的行;
- 若患者所有随访均未复发,保留随访1的行。
期望输出结果:
| ID | FOLLOW_UP | RECURRENCE | RECURRENCE_DATE |
|---|---|---|---|
| 15 | 2 | yes | 2003-05-15 |
| 16 | 1 | no | |
| 29 | 1 | yes | 2002-06-10 |
| 34 | 1 | yes | 2009-11-15 |
| 36 | 1 | no |
可复现代码:
df <- data.frame(ID = c("15", "15", "16","29", "29", "34","34", "34", "36","36"), FOLLOW_UP = c("1", "2", "1","1", "2", "1","2", "3", "1","2"), RECURRENCE = c("no", "yes", "no","yes", "yes", "yes","no", "yes", "no","no"), RECURRENCE_DATE = c("", "2003-05-15", "","2002-06-10", "2002-12-16", "2009-11-15","", "2012-05-03", "","") )
考虑用group_by和slice函数,但不知道如何添加条件实现需求,寻求帮助。
解决方案
可以用dplyr包的分组+排序+切片逻辑实现,核心是给每条记录设定优先级,再按优先级筛选:
代码实现
library(dplyr) df_result <- df %>% # 预处理字段:转换随访次数为整数,空日期转为NA并转成日期格式 mutate( FOLLOW_UP = as.integer(FOLLOW_UP), RECURRENCE_DATE = ifelse(RECURRENCE_DATE == "", NA, RECURRENCE_DATE), RECURRENCE_DATE = as.Date(RECURRENCE_DATE) ) %>% # 按患者ID分组 group_by(ID) %>% # 排序规则:复发记录优先,复发记录按日期升序(最早在前),未复发按随访次数升序 arrange(desc(RECURRENCE == "yes"), RECURRENCE_DATE, FOLLOW_UP) %>% # 取每组第一条(优先级最高的记录) slice(1) %>% ungroup() %>% # 把日期字段的NA转回空字符串,和原始格式对齐 mutate(RECURRENCE_DATE = ifelse(is.na(RECURRENCE_DATE), "", as.character(RECURRENCE_DATE))) # 查看结果 print(df_result)
逻辑说明
- 字段预处理:把字符串类型的随访次数转成整数,空日期转为
NA并转成日期格式,方便后续排序; - 排序优先级:
desc(RECURRENCE == "yes")让所有复发记录(yes)排在未复发记录前面,满足"有复发则优先保留复发记录"的规则;- 复发记录内部按
RECURRENCE_DATE升序,确保最早的复发日期排在第一; - 未复发记录内部按
FOLLOW_UP升序,确保随访1排在第一;
- 切片取数:每组排序后的第一条就是符合要求的记录,用
slice(1)直接提取即可。
内容的提问来源于stack exchange,提问作者lM__3
相关产品推荐
相关产品推荐

