基于匹配子串合并Pandas DataFrame的技术实现问询
问题描述
需求:在df1的Reason列(包含长字符串)中匹配df2的InvoiceID子串,合并两个DataFrame以获取Amount字段。此前在Excel中通过Index Match加通配符*实现该功能。
现有数据:
import pandas as pd data1={'ID':['A','B','A','C'],'Reason':['xxxABC1','yyyBCD2','zzzXY3',"ppp123c"],'Amount':[10,20,30,10]} df1=pd.DataFrame(data1) data2={'ID':['A','B','A','C'],'InvoiceID':['ABC1','BCD2','XY3',"123c"]} df2=pd.DataFrame(data2)
期望结果:
data3={'ID':['A','B','A','C'],'InvoiceID':['ABC1','BCD2','XY3',"123c"],'Amount':[10,20,30,10]} df3=pd.DataFrame(data3)
当前进展:已使用df4=(df1[df1['Reason'].str.contains('ABC1', regex=False)])筛选出匹配行,但不知如何将Amount字段整合到df2生成df3;考虑过循环遍历,但未找到合适方法;尝试过fuzzy wuzzy但因Reason列过长未成功。
解决方案
方法一:apply逐行匹配(直观易读)
通过对df2的每个InvoiceID,在df1中找到Reason包含该子串的行,提取对应的Amount:
def get_matching_amount(invoice_id): # 筛选Reason包含当前InvoiceID的行,取第一个匹配的Amount matched_rows = df1[df1['Reason'].str.contains(invoice_id, regex=False)] return matched_rows['Amount'].iloc[0] if not matched_rows.empty else None # 为df2添加Amount列 df2['Amount'] = df2['InvoiceID'].apply(get_matching_amount)
执行后df2即为期望的df3。
方法二:向量化正则匹配(高效适用于大数据集)
利用正则提取+合并操作,避免逐行循环,提升效率:
# 将所有InvoiceID拼接成正则表达式,匹配任意位置的子串 invoice_regex = '|'.join(df2['InvoiceID']) # 从df1的Reason中提取匹配的InvoiceID df1['matched_invoice'] = df1['Reason'].str.extract(f'({invoice_regex})', expand=False) # 按匹配的InvoiceID合并两个DataFrame df3 = df2.merge( df1[['matched_invoice', 'Amount']], left_on='InvoiceID', right_on='matched_invoice', how='left' ).drop('matched_invoice', axis=1)
注意事项
- 如果存在多个InvoiceID匹配同一Reason的情况,需根据业务需求调整逻辑(如取第一个匹配项、求和等)
str.contains中设置regex=False,确保InvoiceID中的特殊字符(如+、.)不会被当作正则语法解析,避免匹配错误
内容的提问来源于stack exchange,提问作者Laura Stock
相关产品推荐
相关产品推荐

