如何基于唯一字符列合并多列事件数据的多行记录(dplyr实现)
合并患者多行疾病记录(dplyr解决方案)
现有数据集d中,pnr是唯一患者标识,age.hl、kon.hl、sen.hl、mix.hl分别代表四种疾病的发生状态(1=事件发生,0=事件未发生),对应的xxx.hl.time是事件发生时间;未发生事件时,时间统一为截尾日期2018-12-31,且同一疾病的发生事件(值为1)不会在同一患者的多行记录中重复出现。
需按pnr合并记录,使每个患者仅保留一行,整合所有疾病的状态与对应时间。
原始数据集
d <- data.frame( pnr = c("A", "A", "A", "B", "C", "C"), age.hl = c(0, 1, 0, 0, 0, 1), age.hl.time = c(as.Date("2018-12-31"), as.Date("2013-10-31"), as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2008-07-31")), kon.hl = c(1, 0, 0, 0, 0, 0), kon.hl.time = c(as.Date("2011-02-01"), as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2018-12-31")), sen.hl = c(0, 0, 1, 1, 0, 1), sen.hl.time = c(as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2016-09-30"), as.Date("2004-04-30"), as.Date("2018-12-31"), as.Date("2009-01-31")), mix.hl = c(0, 1, 0, 0, 1, 0), mix.hl.time = c(as.Date("2018-12-31"), as.Date("2013-10-31"), as.Date("2018-12-31"), as.Date("2018-12-31"), as.Date("2006-01-17"), as.Date("2018-12-31")) )
原始数据预览:
> d pnr age.hl age.hl.time kon.hl kon.hl.time sen.hl sen.hl.time mix.hl mix.hl.time 1 A 0 2018-12-31 1 2011-02-01 0 2018-12-31 0 2018-12-31 2 A 1 2013-10-31 0 2018-12-31 0 2018-12-31 1 2013-10-31 3 A 0 2018-12-31 0 2018-12-31 1 2016-09-30 0 2018-12-31 4 B 0 2018-12-31 0 2018-12-31 1 2004-04-30 0 2018-12-31 5 C 0 2018-12-31 0 2018-12-31 0 2018-12-31 1 2006-01-17 6 C 1 2008-07-31 0 2018-12-31 1 2009-01-31 0 2018-12-31
期望输出
pnr age.hl age.hl.time kon.hl kon.hl.time sen.hl sen.hl.time mix.hl mix.hl.time 1 A 1 2013-10-31 1 2011-02-01 1 2016-09-30 1 2013-10-31 2 B 0 2018-12-31 0 2018-12-31 1 2004-04-30 0 2018-12-31 3 C 1 2008-07-31 0 2018-12-31 1 2009-01-31 1 2006-01-17
dplyr解决方案
利用dplyr的分组聚合功能,对每个患者的疾病状态取最大值(1代表发生,0代表未发生,最大值即为该患者是否发生过该疾病),对应时间取最小值(事件发生时间早于截尾日期,取最小即可得到实际发生时间;未发生时所有时间均为截尾日期,取最小不影响结果)。
代码如下:
library(dplyr) d_merged <- d %>% group_by(pnr) %>% summarise( age.hl = max(age.hl), age.hl.time = min(age.hl.time), kon.hl = max(kon.hl), kon.hl.time = min(kon.hl.time), sen.hl = max(sen.hl), sen.hl.time = min(sen.hl.time), mix.hl = max(mix.hl), mix.hl.time = min(mix.hl.time), .groups = "drop" # 聚合后取消分组 ) # 查看合并结果 print(d_merged)
代码说明
group_by(pnr):按患者标识分组summarise:对每组字段做聚合操作:- 疾病状态字段(如
age.hl)取max():同一患者同一疾病最多仅1条发生记录,最大值即为该患者的疾病发生状态 - 时间字段(如
age.hl.time)取min():事件发生时间早于截尾日期,取最小能得到实际发生时间;未发生时所有时间均为截尾日期,取最小仍为该日期
- 疾病状态字段(如
.groups = "drop":取消分组,返回普通数据框
执行代码后即可得到期望的合并结果。
内容的提问来源于stack exchange,提问作者cmirian
相关产品推荐
相关产品推荐

