如何高效遍历Pandas DataFrame匹配患者门诊住院记录
Pandas门诊-住院记录匹配性能优化方案
问题根因
你当前使用的双层for循环实现时间复杂度为O(nm),随着数据量增长耗时会呈线性叠加甚至指数级上涨,且原有代码存在语法错误、索引引用错误(内层循环索引j未被使用,所有判断都取了外层索引i的值),本身无法得到正确匹配结果。
这类「按主体分组、匹配时间点之后最近的对应事件」是典型的时间序列最近邻关联场景,无需手写循环,使用Pandas内置的专用函数即可实现O(n log n)*级别的性能,在百万级数据集上也能在数秒内返回结果。
最优实现方案
使用pandas.merge_asof实现,该函数原生支持按关键字分组、按指定方向做最近邻匹配,完全适配你的业务需求:
- 前置排序:匹配前需要保证两个表都按「患者ID+时间字段」升序排列
- 配置匹配规则:按
patient_key分组隔离不同患者的数据,匹配方向设为forward,即仅查找时间晚于门诊预约时间的最近一条住院记录
完整代码如下:
import pandas as pd # 1. 预处理:两个表均按患者+对应时间字段升序排序 df1 = df1.sort_values(by=["patient_key", "admission_dtm"]).reset_index(drop=True) df2 = df2.sort_values(by=["patient_key", "appointment_dtm"]).reset_index(drop=True) # 2. 执行向前最近邻匹配 df_result = pd.merge_asof( df2, df1, by="patient_key", # 按患者ID分组,避免跨患者错配 left_on="appointment_dtm", # 左表(门诊表)匹配用时间字段 right_on="admission_dtm", # 右表(住院表)匹配用时间字段 direction="forward" # 仅找时间在门诊之后的最近住院记录 )
结果校验
用你提供的P001示例数据运行上述代码,匹配结果完全符合业务预期:
- 预约时间41645、41687、41717 → 匹配住院时间41765 →
admission_key为P001-001 - 预约时间42162、42193 → 匹配住院时间42223 →
admission_key为P001-002 - 预约时间42497 → 匹配住院时间42681 →
admission_key为P001-003
注意事项
- 若存在门诊预约时间晚于患者最后一次住院时间的记录,匹配到的
admission_key、admission_dtm字段会为空值,可根据业务需求单独过滤或标记这类无后续住院的门诊记录 - 匹配前需确认两个表的时间字段类型一致(同为数值型时间戳或datetime类型),禁止用字符串存储时间,否则会导致匹配逻辑错误
- 若数据量达到千万级,可换用polars库的
join_asof接口,语法逻辑一致,性能比pandas高3~5倍
内容的提问来源于stack exchange,提问作者Isaac Tai
相关产品推荐
相关产品推荐

