使用Python/Pandas实现双表列遍历匹配,为表格新增匹配结果列方法咨询
问题背景
现有两张数据表结构如下:
- 表1:包含
Date(日期)、Prescribed(开具药品)两列,Prescribed每行可存储多种药品信息,多以逗号分隔 - 表2:包含
Name(药品名称)、Category(药品分类)两列,Name列通常为带剂型、剂量的完整药品名
需求为给表1新增匹配结果列:若Prescribed列内容包含任意一个表2Name列中存在的药品通用名(示例:表1Prescribed含Amlodipine,表2Name存在Amlodipine (Amlodipine | 10 mg | Tablet)时返回True),整行返回True,否则返回False。
原有方案全False的原因
原有代码逻辑核心方向没问题,但遗漏了几个关键细节导致匹配失败:
- 格式不一致问题:未处理大小写差异、字符串前后空格,比如拆分后的
Amlodipine(带前置空格)无法匹配表2的Amlodipine开头的名称 - 行级聚合逻辑缺失:原有代码对每个拆分后的药品单独输出结果,没有聚合到整行维度——只要有一个药品匹配成功,整行就应该返回True,不需要判断剩余药品
- 部分场景下逻辑写反:如果表2
Name是短的通用名,表1Prescribed是长的完整处方,原有str(b) in s的判断就会完全反向
可行解决方案
推荐用pandas向量化操作实现,效率远高于原生for循环:
import pandas as pd import re # 1. 数据预处理:统一转小写、去除两端冗余空格 table1['Prescribed_clean'] = table1['Prescribed'].str.strip().str.lower() table2['Name_clean'] = table2['Name'].str.strip().str.lower() # 2. 提取表2的所有药品通用名(可选优化:提取括号前的核心名称,减少匹配噪音) table2['drug_core'] = table2['Name_clean'].str.extract(r'^([^\(]+)\s*\(')[0].str.strip() # 过滤空值后生成匹配关键词列表 drug_keywords = table2['drug_core'].dropna().unique().tolist() # 3. 预编译正则表达式,提升匹配速度 pattern = re.compile('|'.join(map(re.escape, drug_keywords))) # 4. 对表1每行做匹配,生成结果列 table1['match_result'] = table1['Prescribed_clean'].str.contains(pattern, na=False)
如果不需要提取核心名称,直接匹配表2Name任意子串,可替换第三步、第四步的逻辑:
# 直接判断Prescribed是否包含任意表2Name的子串 all_drug_names = table2['Name_clean'].unique().tolist() table1['match_result'] = table1['Prescribed_clean'].apply(lambda x: any(key in x for key in all_drug_names))
代码优化建议
- 避免用原生for循环遍历DataFrame行,pandas的
str系列方法和apply结合预编译正则的效率是原生循环的10~100倍 - 提前做数据清洗:统一大小写、去空格、处理空值,能避免90%以上的无意义匹配失败
- 样本量超过10万行时,可以提前对匹配关键词去重,减少正则表达式的长度,进一步提升速度
相关学习资料推荐
- pandas官方文本处理模块文档:系统了解
str类所有内置方法,覆盖绝大多数结构化文本处理需求 - Python正则表达式官方教程:掌握正则的基础语法、分组、预编译等优化技巧,大幅提升复杂匹配场景的开发效率
- pandas性能优化实操指南:了解向量化运算、
apply、iterrows、原生循环的性能差异,学会根据数据量选择最优实现方案
内容的提问来源于stack exchange,提问作者PhxIT
相关产品推荐
相关产品推荐

