pandas部分字符串匹配合并不等长DataFrame问题咨询
错误原因
你的代码存在两个核心逻辑问题:
- 第一步匹配标记逻辑本身是正确的:
str.contains是子串匹配规则,只要Ref字段任意位置包含Invoice列的任意值就会标记为True,因此INV20562、INV20563BG因为内嵌对应数字串被正确标记为匹配。 - 第二步值提取逻辑错误:你对
Ref做str.split()时,所有Ref值都不含空格,split后整个转小写的字符串(比如inv20562)是列表的唯一元素;后续判断该元素是否在Invoice列表中时,Invoice存储的是纯数字串20562,和inv20562完全不相等,自然匹配不到、返回空列表。
另外你的代码中冗余了一行df1['Invoice'].tolist()]),属于笔误,不影响运行但无实际作用。
高性能实现方案
你的场景是小表(115行)匹配大表(60万行),优先使用pandas内置的C层向量化字符串操作,避免用apply(本质是Python层逐行循环,大数据量下性能极差),通过正则一步完成匹配和提取即可:
import pandas as pd import re # 构造示例数据 df1 = pd.DataFrame({'Invoice': ['20561', '20562', '20563', '20564'], 'Currency': ['EUR', 'EUR', 'EUR', 'USD']}) df2 = pd.DataFrame({'Ref': ['20561', 'INV20562', 'INV20563BG', '20564'], 'Type': ['01', '03', '04', '02'], 'Amount': ['150', '175', '160', '180'], 'Comment': ['bla', 'bla', 'bla', 'bla']}) # 构造匹配正则,re.escape避免Invoice值含正则特殊字符导致匹配异常 pattern = '|'.join(map(re.escape, df1['Invoice'])) # 全向量化操作,60万行数据可在毫秒级完成 df2['compMatch'] = df2['Ref'].str.contains(pattern) # 提取第一个匹配到的Invoice值,若需提取所有匹配值把extract换成findall即可 df2['matchedName'] = df2['Ref'].str.extract(f'({pattern})', expand=False) # 过滤未匹配行 df2_matched = df2[df2['compMatch']].copy()
运行结果如下:
print(df2_matched) Ref Type Amount Comment compMatch matchedName 0 20561 01 150 bla True 20561 1 INV20562 03 175 bla True 20562 2 INV20563BG 04 160 bla True 20563 3 20564 02 180 bla True 20564
如果需要关联df1的其他字段(比如示例中的Currency),直接做左连接即可,因为df1行数极少,merge操作几乎无性能开销:
df_result = df2_matched.merge(df1, left_on='matchedName', right_on='Invoice', how='left')
补充说明
- 如果单个
Ref字段可能包含多个Invoice号,把str.extract换成str.findall(pattern)即可,返回结果是所有匹配到的Invoice值组成的列表,和你原本matchedName的格式完全一致。 - 构造正则时加
re.escape是通用兼容写法,纯数字Invoice场景下不加也能运行,但可以覆盖后续Invoice值出现.、*等特殊字符的情况,避免匹配逻辑异常。
内容的提问来源于stack exchange,提问作者Mojumder
相关产品推荐
相关产品推荐

