Pandas校验成对FITM/SERVDT生成med_consult字段方法
简洁实现方案
针对穿插排列的配对字段校验场景,不需要逐组编写重复判断逻辑,使用pandas.wide_to_long做宽表转长表处理,可自动对齐同序号的配对字段,批量完成规则校验,代码逻辑不会随配对字段组数增加而冗余,扩展到FITM1~FITM7全量字段时无需修改核心代码。
完整实现代码
import pandas as pd # ------------ 样例数据初始化(和提供的测试数据一致)------------ # 注意:Python3不支持整数前导0写法,原编码0305实际对应字符串匹配时为'0305'、数值匹配时为305 msp_codes = [310, 311, 305, 308, 910] # 统一将编码转为字符串集合,和DataFrame中FITM列的字符串类型对齐,避免类型不匹配导致匹配失败 msp_codes_set = {str(code) for code in msp_codes} patients = [ ("1", '2022-11-13', '2022-11-15', "310", "2022-11-14", "M3200", "00456", "2022-11-14", "G456"), ("2", '2022-11-10', '2022-11-22', "007", "2022-11-14", "M05", "0033", "2022-11-20", "G456"), ("3", '2022-11-09', '2022-11-13', "309", "2022-10-14", "N058", "308", "2021-10-02", "F70"), ] labels = ["ID", 'ADMIT_DATE', 'SURG_DATE', "FITM1", "SERVDT1", "CLMSPEC1", "FITM2", "SERVDT2", "CLMSPEC2"] df_patients = pd.DataFrame.from_records(patients, columns=labels) date_cols = ['ADMIT_DATE', 'SURG_DATE', 'SERVDT1', 'SERVDT2'] df_patients[date_cols] = df_patients[date_cols].apply(pd.to_datetime, errors='coerce') # ------------ 核心处理逻辑 ------------ # 宽表转长表,自动对齐同序号的FITM、SERVDT、CLMSPEC字段 df_long = pd.wide_to_long( df_patients, stubnames=["FITM", "SERVDT", "CLMSPEC"], # 按前缀提取需要的字段组 i=["ID", "ADMIT_DATE", "SURG_DATE"], # 单条患者记录的唯一标识字段 j="group_seq" # 存储原字段末尾序号的列名 ).reset_index() # 向量化批量校验两个判定条件 df_long["is_match"] = ( df_long["FITM"].isin(msp_codes_set) & (df_long["SERVDT"] >= df_long["ADMIT_DATE"]) & (df_long["SERVDT"] <= df_long["SURG_DATE"]) ) # 按患者聚合,任意一组满足条件即标记为1 med_consult_flag = df_long.groupby("ID")["is_match"].any().astype(int).rename("med_consult") # 合并标记结果回原表,得到最终输出 df_result = df_patients.merge(med_consult_flag, on="ID")
逻辑说明
- 选择
wide_to_long而非手动melt的原因:该函数可直接按字段名前缀+末尾序号的规则,自动将穿插在表中的同组字段对齐到同一行,不需要手动筛选、拼接多组字段,后续扩展到7组变量时仅需保证字段命名符合前缀+序号的规则即可,无需修改核心代码。 - 所有判断均为pandas向量化操作,执行效率远高于逐行循环、逐组写
np.select判断的实现,数据量较大时性能优势明显。 - 提前统一编码类型为集合做匹配,避免字符串/数值类型不一致导致的匹配失效问题,集合的
isin判断效率高于列表。
运行代码后输出结果和预期完全一致:
第1行:FITM1=310属于目标编码列表,对应服务日期在入院、手术日期区间内,
med_consult=1
第2行:所有FITM字段取值均不在目标编码列表中,med_consult=0
第3行:FITM2=308属于目标编码列表,但对应服务日期早于入院日期,不满足区间要求,med_consult=0
内容的提问来源于stack exchange,提问作者Eoin Vaughan
相关产品推荐
相关产品推荐

