Python中基于子串匹配关联两个Pandas DataFrame并提取对应列值
解决Pandas DataFrame子串匹配并合并AttrName的问题
嘿,这个子串匹配合并的需求我熟!下面给你两种实用的解决方案,分别适合不同规模的数据集:
先准备示例数据
首先咱们先把你给出的两个DataFrame用代码构造出来,方便后续测试:
import pandas as pd # 创建df1 df1 = pd.DataFrame({ 'ACNo': [12340, 23867, 98372, 9837, 54332], 'Product': ['100% Hot Care', 'Auction5', 'Edition', 'Diet Parameter', 'Load'] }) # 创建df2 df2 = pd.DataFrame({ 'ProdDetail': ['12345.567', 'Model1 Count\\100% Hot Care Recipe', '123445\\Handle Improve', 'Diet Edition\\Parameter Amount'], 'AttrName': ['Age Confirmation', 'Recipe', 'Improve', 'Amount'] })
方法一:逐行匹配(小数据集友好)
如果你的数据量不大,用apply配合自定义函数就能快速搞定。这个方法逻辑直观,容易理解:
# 定义一个函数,输入Product值,返回匹配到的AttrName def get_matching_attr(product): # 筛选df2中ProdDetail包含当前Product的行 matched_rows = df2[df2['ProdDetail'].str.contains(product, na=False)] # 如果有匹配结果,返回第一个匹配的AttrName;没有则返回空值 return matched_rows.iloc[0]['AttrName'] if not matched_rows.empty else pd.NA # 将函数应用到df1的Product列,生成新的AttrName列 df1['AttrName'] = df1['Product'].apply(get_matching_attr)
运行后df1的结果如下:
ACNo Product AttrName 0 12340 100% Hot Care Recipe 1 23867 Auction5 <NA> 2 98372 Edition Amount 3 9837 Diet Parameter Amount 4 54332 Load <NA>
方法二:矢量化交叉匹配(大数据集高效)
如果你的数据集很大,逐行apply会比较慢,这时候可以用矢量化的交叉匹配方法,利用Pandas的批量操作提升效率:
# 生成df1和df2的全交叉组合 cross_merged = df1.assign(temp_key=1).merge(df2.assign(temp_key=1), on='temp_key').drop('temp_key', axis=1) # 标记哪些组合是子串匹配的 cross_merged['is_match'] = cross_merged.apply(lambda row: row['Product'] in row['ProdDetail'], axis=1) # 筛选出匹配的行,再合并回原df1(保留所有原始行) final_result = df1.merge( cross_merged[cross_merged['is_match']][['ACNo', 'AttrName']], on='ACNo', how='left' )
额外处理:多个匹配结果的情况
如果同一个Product在df2中对应多个AttrName,你可以用分组聚合把结果合并成一个字符串,比如:
# 把同一个ACNo对应的所有AttrName用逗号分隔合并 aggregated_attrs = cross_merged[cross_merged['is_match']].groupby('ACNo')['AttrName'].agg(', '.join).reset_index() # 合并回df1 df1 = df1.merge(aggregated_attrs, on='ACNo', how='left')
内容的提问来源于stack exchange,提问作者amark
相关产品推荐
相关产品推荐

