You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于匹配子串合并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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:50:29