基于AND条件与严格匹配的DataFrame发票支付匹配问题
问题描述
需要将df1中DocN列的发票支付记录与df2中TXT列的数据匹配,同时满足DocArt1与DocArt2严格相等的条件,最终输出包含DocN、DocSum及对应支付详情(DocP、Date)的结果表。现有代码无法得到预期输出,需排查修正。
原始数据集
df1(发票数据)
| DocN | DocSum | DocArt1 |
|---|---|---|
| INV001 | 1000 | A001 |
| INV002 | 2500 | B002 |
| INV003 | 1500 | A001 |
df2(支付数据)
| DocP | Date | TXT | DocArt2 |
|---|---|---|---|
| PAY001 | 2024-01-10 | 支付INV001 | A001 |
| PAY002 | 2024-01-15 | 支付INV002 | B002 |
| PAY003 | 2024-01-20 | 支付INV001 | A001 |
| PAY004 | 2024-01-25 | 支付INV003 | A001 |
尝试代码
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'DocN': ['INV001', 'INV002', 'INV003'], 'DocSum': [1000, 2500, 1500], 'DocArt1': ['A001', 'B002', 'A001'] }) df2 = pd.DataFrame({ 'DocP': ['PAY001', 'PAY002', 'PAY003', 'PAY004'], 'Date': ['2024-01-10', '2024-01-15', '2024-01-20', '2024-01-25'], 'TXT': ['支付INV001', '支付INV002', '支付INV001', '支付INV003'], 'DocArt2': ['A001', 'B002', 'A001', 'A001'] }) # 尝试的匹配逻辑 result = pd.merge(df1, df2, left_on='DocN', right_on='TXT', how='left') result = result[result['DocArt1'] == result['DocArt2']] result = result[['DocN', 'DocSum', 'DocP', 'Date']]
预期输出
| DocN | DocSum | DocP | Date |
|---|---|---|---|
| INV001 | 1000 | PAY001 | 2024-01-10 |
| INV001 | 1000 | PAY003 | 2024-01-20 |
| INV002 | 2500 | PAY002 | 2024-01-15 |
| INV003 | 1500 | PAY004 | 2024-01-25 |
问题排查与修正
问题根源
原代码直接用DocN和TXT做merge匹配,但TXT是包含DocN的字符串(如支付INV001),并非与DocN完全相等,导致匹配失败,无法得到有效结果。
修正代码
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'DocN': ['INV001', 'INV002', 'INV003'], 'DocSum': [1000, 2500, 1500], 'DocArt1': ['A001', 'B002', 'A001'] }) df2 = pd.DataFrame({ 'DocP': ['PAY001', 'PAY002', 'PAY003', 'PAY004'], 'Date': ['2024-01-10', '2024-01-15', '2024-01-20', '2024-01-25'], 'TXT': ['支付INV001', '支付INV002', '支付INV001', '支付INV003'], 'DocArt2': ['A001', 'B002', 'A001', 'A001'] }) # 从TXT中提取DocN(适配"支付+DocN"的格式) df2['extracted_DocN'] = df2['TXT'].str.extract(r'(INV\d+)') # 多条件合并:同时匹配DocN和DocArt字段 result = pd.merge( df1, df2, left_on=['DocN', 'DocArt1'], right_on=['extracted_DocN', 'DocArt2'], how='left' ) # 筛选目标列并去除未匹配的空值行 result = result[['DocN', 'DocSum', 'DocP', 'Date']].dropna().reset_index(drop=True) print(result)
修正说明
- 提取匹配字段:用正则表达式从
TXT中提取出纯DocN值,解决字符串不完全匹配的问题。 - 多条件合并:合并时同时校验
DocN和DocArt两个条件,确保匹配逻辑的严谨性,避免后续额外过滤操作。 - 结果清理:移除
left join产生的未匹配空值行,得到符合预期的结果集。
内容的提问来源于stack exchange,提问作者user534280
相关产品推荐
相关产品推荐

