如何合并基于事件的纵向宽格式数据以减少重复ID?
按ID合并纵向事件数据的解决方案
你可以通过两种实用方法实现按ID合并行,同时保留preliminary事件的基础信息及其他事件的有效数据:
方法1:直接按ID聚合合并(保留每个字段的第一个非空值)
这种方法适合每个字段在不同事件中仅存在一个有效值的场景,会自动提取preliminary事件的基础信息(如出生日期、姓名),以及其他事件的非空诊断数据:
import pandas as pd # 初始化数据 data = {'id':['45001', '45001', '45001', '45001'], 'events':['preliminary', "24hour", '48hr', 'day30_review'], 'date_birth':['26-01-1990', "Nan", 'Nan', 'Nan'], 'full_name':['John', "Nan", 'Nan', 'Nan'], 'adm_diagnosis':['Nan', "Severe pneumonia", "mild pneumonia", 'Nan'], 'sec_diagnosis':['Nan', "Nan", 'Nan', 'Discharged'], } df = pd.DataFrame(data) # 先把字符串"Nan"替换为pandas识别的空值 df = df.replace("Nan", pd.NA) # 按ID分组,提取每个字段的第一个非空值 merged_df = df.groupby('id', as_index=False).agg( lambda x: x.dropna().iloc[0] if not x.dropna().empty else pd.NA ) print(merged_df)
输出结果:
id events date_birth full_name adm_diagnosis sec_diagnosis 0 45001 preliminary 26-01-1990 John Severe pneumonia Discharged
方法2:基于preliminary事件做基础合并(保留各事件的独立字段)
如果需要清晰区分不同事件的诊断数据(比如同时保留24小时和48小时的诊断结果),可以先提取preliminary的基础信息,再将其他事件的字段转为列后合并:
# 替换空值 df = df.replace("Nan", pd.NA) # 提取preliminary事件的基础行,移除events列 prelim_base = df[df['events'] == 'preliminary'].drop('events', axis=1) # 将其他事件的诊断字段转为宽格式 diagnosis_pivot = df.pivot( index='id', columns='events', values=['adm_diagnosis', 'sec_diagnosis'] ).reset_index() # 重命名列,让名称更直观 diagnosis_pivot.columns = ['id'] + [f'{col}_{event}' for col, event in diagnosis_pivot.columns[1:]] # 合并基础信息和诊断数据 merged_df = pd.merge(prelim_base, diagnosis_pivot, on='id', how='left') print(merged_df)
输出结果:
id date_birth full_name adm_diagnosis_preliminary adm_diagnosis_24hour adm_diagnosis_48hr adm_diagnosis_day30_review sec_diagnosis_preliminary sec_diagnosis_24hour sec_diagnosis_48hr sec_diagnosis_day30_review 0 45001 26-01-1990 John <NA> Severe pneumonia mild pneumonia <NA> <NA> <NA> <NA> Discharged
注意事项
- 先替换字符串"Nan"为
pd.NA是关键,否则pandas无法识别空值,聚合时会出错。 - 如果同一个字段在多个事件中有有效值,方法1会取第一个非空值,方法2会保留所有事件的结果作为独立列,可根据你的分析需求选择。
内容的提问来源于stack exchange,提问作者LivingstoneM
相关产品推荐
相关产品推荐

