Pandas实现患者诊断后随访标记及分科室统计的技术咨询
随访统计需求的Pandas解决方案
1. 单患者维度统计
需求说明
统计确诊疾病后有后续随访的患者数量(及占比),需先标记每条预约记录是否为诊断后的随访(fup_yn),再按patient_id聚合统计。
原始数据示例
import pandas as pd data_single = [ [1, '2024-01-11', pd.NaT, pd.NA], [1, '2024-03-14', '2024-03-14', 1], [1, '2024-04-09', pd.NaT, pd.NA], [1, '2024-09-09', pd.NaT, pd.NA] ] df_single = pd.DataFrame(data_single, columns=['patient_id', 'app_date', 'diag_date', 'cancer_yn']) df_single['app_date'] = pd.to_datetime(df_single['app_date']) df_single['diag_date'] = pd.to_datetime(df_single['diag_date'])
步骤1:标记随访记录(fup_yn)
核心逻辑:为每个患者确定最早确诊日期,判断预约日期是否晚于确诊日期(确诊当天不算随访),无确诊记录的患者所有记录标记为0。
# 获取每个患者的最早确诊日期 patient_diag_dates = df_single[df_single['cancer_yn'] == 1].groupby('patient_id')['diag_date'].min().reset_index() # 合并确诊日期到原数据 df_single = df_single.merge(patient_diag_dates, on='patient_id', suffixes=('', '_confirmed'), how='left') # 标记随访状态 df_single['fup_yn'] = df_single.apply( lambda row: 1 if pd.notna(row['diag_date_confirmed']) and row['app_date'] > row['diag_date_confirmed'] else 0, axis=1 ) # 移除临时列 df_single.drop('diag_date_confirmed', axis=1, inplace=True)
生成的中间DF如下:
| patient_id | app_date | diag_date | cancer_yn | fup_yn |
|---|---|---|---|---|
| 1 | 2024-01-11 | NaT | NaN | 0 |
| 1 | 2024-03-14 | 2024-03-14 | 1 | 0 |
| 1 | 2024-04-09 | NaT | NaN | 1 |
| 1 | 2024-09-09 | NaT | NaN | 1 |
步骤2:聚合统计患者随访状态
# 判断每个患者是否存在随访记录 patient_fup_status = df_single.groupby('patient_id')['fup_yn'].max().reset_index() patient_fup_status.columns = ['patient_id', 'patient_with_fup'] # 统计各状态的患者数量 final_summary = patient_fup_status['patient_with_fup'].value_counts().reset_index() final_summary.columns = ['patient_with_fup', 'count']
最终汇总DF示例:
| patient_with_fup | count |
|---|---|
| 1 | 24 |
| 0 | 67 |
2. 科室维度统计
需求说明
扩展至多科室场景,同一患者可能在多个科室确诊,需按dept和patient_id分组,标记并统计各科室下有随访的患者数。
原始数据示例
data_dept = [ ['Radiology', 1, '2024-01-11', pd.NaT, pd.NA], ['Radiology', 1, '2024-03-14', '2024-03-14', 1], ['Radiology', 1, '2024-04-09', pd.NaT, pd.NA], ['Radiology', 1, '2024-09-09', pd.NaT, pd.NA], ['Respiratory', 1, '2024-02-11', pd.NaT, pd.NA], ['Respiratory', 1, '2024-04-14', '2024-04-14', 1], ['Respiratory', 1, '2024-06-09', pd.NaT, pd.NA], ['Respiratory', 1, '2024-09-09', pd.NaT, pd.NA], ['Respiratory', 2, '2024-01-11', pd.NaT, pd.NA], ['Respiratory', 2, '2024-03-14', '2024-03-14', 1], ['Respiratory', 2, '2024-04-09', pd.NaT, pd.NA], ['Respiratory', 2, '2024-09-09', pd.NaT, pd.NA] ] df_dept = pd.DataFrame(data_dept, columns=['dept', 'patient_id', 'app_date', 'diag_date', 'diag_yn']) df_dept['app_date'] = pd.to_datetime(df_dept['app_date']) df_dept['diag_date'] = pd.to_datetime(df_dept['diag_date'])
步骤1:标记科室维度的随访记录
核心逻辑:按「科室+患者」组合确定最早确诊日期,判断该组合下的预约是否为随访。
# 获取每个(科室+患者)组合的最早确诊日期 dept_patient_diag = df_dept[df_dept['diag_yn'] == 1].groupby(['dept', 'patient_id'])['diag_date'].min().reset_index() # 合并确诊日期到原数据 df_dept = df_dept.merge(dept_patient_diag, on=['dept', 'patient_id'], suffixes=('', '_confirmed'), how='left') # 标记随访状态 df_dept['fup_yn'] = df_dept.apply( lambda row: 1 if pd.notna(row['diag_date_confirmed']) and row['app_date'] > row['diag_date_confirmed'] else 0, axis=1 ) # 移除临时列 df_dept.drop('diag_date_confirmed', axis=1, inplace=True)
步骤2:按科室聚合统计患者随访状态
# 判断每个(科室+患者)组合是否存在随访记录 dept_patient_fup = df_dept.groupby(['dept', 'patient_id'])['fup_yn'].max().reset_index() dept_patient_fup.columns = ['dept', 'patient_id', 'patient_with_fup'] # 按科室统计各状态的患者数量 final_dept_summary = dept_patient_fup.groupby(['dept', 'patient_with_fup']).size().reset_index(name='count') # 整理为预期的展示格式 final_dept_summary = final_dept_summary.pivot(index='dept', columns='patient_with_fup', values='count').fillna(0).reset_index() final_dept_summary = final_dept_summary.melt(id_vars='dept', var_name='patient_with_fup', value_name='count') final_dept_summary['count'] = final_dept_summary['count'].astype(int)
最终输出DF示例:
| dept | patient_with_fup | count |
|---|---|---|
| Radiology | 1 | 1 |
| Radiology | 0 | 0 |
| Respiratory | 1 | 2 |
| Respiratory | 0 | 0 |
内容的提问来源于stack exchange,提问作者Eoin Vaughan
相关产品推荐
相关产品推荐

