如何修正基于关键词匹配两个Pandas DataFrame生成目标DataFrame的代码
解决Pandas DataFrame关键词匹配错误的问题
问题场景
现有两个Pandas DataFrame:df1和df2,需求是:
- 当
df2['ColD']中的完整关键词出现在df1['ColE']的文本内容中时,将df2对应行的ColA、ColB、ColC值分别合并到df1的ColA0、ColB0、ColC0列 - 把匹配到的关键词存入
ColD1列,生成目标DataFramedf01
当前代码运行后出现错误:df1第二行文本仅包含d2,却错误匹配了d1对应的A1、B1、C1,不符合预期。
错误原因分析
大概率是原有代码存在以下问题之一:
- 仅使用模糊的
str.contains()匹配,未处理关键词边界(比如文本中的d12会被误判为包含d1) - 匹配逻辑未按精确匹配顺序执行,导致无关关键词被优先匹配
- 使用了不合适的合并方式(如直接
merge),未做逐行的精准关键词校验
正确解决方案
步骤1:构造测试示例数据
先模拟你的数据场景,方便验证:
import pandas as pd import re # 示例df1:待匹配的文本数据 df1 = pd.DataFrame({ 'ColE': ['文本包含d1关键词', '文本里只有d2', '同时包含d1和d3'] }) # 示例df2:关键词映射表 df2 = pd.DataFrame({ 'ColA': ['A1', 'A2', 'A3'], 'ColB': ['B1', 'B2', 'B3'], 'ColC': ['C1', 'C2', 'C3'], 'ColD': ['d1', 'd2', 'd3'] })
步骤2:实现精准匹配逻辑
用apply结合正则边界校验,确保只匹配完整关键词:
# 构建关键词到对应字段的映射字典 key_map = df2.set_index('ColD')[['ColA', 'ColB', 'ColC']].to_dict('index') # 定义匹配函数:处理单条文本的关键词匹配 def find_matches(text): # 收集所有匹配的完整关键词(用\b确保词边界,re.escape处理特殊字符) matched_keys = [ key for key in key_map.keys() if re.search(rf'\b{re.escape(key)}\b', text) ] if not matched_keys: # 无匹配时返回空值 return pd.Series([None, None, None, None]) # 处理多关键词匹配:用逗号合并所有匹配结果,可按需调整(比如取第一个匹配) col_a_vals = ', '.join([key_map[k]['ColA'] for k in matched_keys]) col_b_vals = ', '.join([key_map[k]['ColB'] for k in matched_keys]) col_c_vals = ', '.join([key_map[k]['ColC'] for k in matched_keys]) matched_str = ', '.join(matched_keys) return pd.Series([col_a_vals, col_b_vals, col_c_vals, matched_str]) # 将匹配结果合并到df1 df1[['ColA0', 'ColB0', 'ColC0', 'ColD1']] = df1['ColE'].apply(find_matches) # 生成目标df01 df01 = df1.copy()
步骤3:验证结果
运行后df01的结果符合预期:
| ColE | ColA0 | ColB0 | ColC0 | ColD1 |
|---|---|---|---|---|
| 文本包含d1关键词 | A1 | B1 | C1 | d1 |
| 文本里只有d2 | A2 | B2 | C2 | d2 |
| 同时包含d1和d3 | A1, A3 | B1, B3 | C1, C3 | d1, d3 |
可选调整
如果只需要第一个匹配到的关键词(而非所有匹配),可以修改find_matches函数:
def find_first_match(text): for key in key_map.keys(): if re.search(rf'\b{re.escape(key)}\b', text): return pd.Series([key_map[key]['ColA'], key_map[key]['ColB'], key_map[key]['ColC'], key]) return pd.Series([None, None, None, None])
内容的提问来源于stack exchange,提问作者Sanket Sathe
相关产品推荐
相关产品推荐

