基于另一DataFrame列的部分字符串匹配为Pandas DataFrame新增列
Pandas高效实现多列部分字符串匹配填充MAKE列
核心思路
先筛选出df1中profile非空的有效行,通过矢量化字符串匹配结合布尔索引批量匹配df2的对应列,彻底替代逐行循环的低效操作。以下是两种可行的高效方案:
方案一:广播+布尔索引批量匹配
适用于中等数据量场景,借助numpy广播生成匹配矩阵,快速定位符合条件的df2记录:
import pandas as pd import numpy as np # 1. 筛选df1中profile非空的行 df1_valid = df1[df1['profile'].notna()].copy() # 2. 将df2的匹配列转为numpy数组,方便广播计算 name_arr = df2['NAME'].to_numpy() pl_arr = df2['PRODUCT_LINE'].to_numpy() size_arr = df2['SIZE'].to_numpy() make_arr = df2['MAKE'].to_numpy() # 3. 生成匹配布尔矩阵:判断df1的列是否是df2对应列的子串(匹配方向可按需互换) match_mask = ( np.char.contains(name_arr[:, None], df1_valid['brand'].to_numpy()) & np.char.contains(pl_arr[:, None], df1_valid['product_line'].to_numpy()) & np.char.contains(size_arr[:, None], df1_valid['size'].to_numpy()) ) # 4. 提取每个有效行对应的第一个匹配MAKE值 match_indices = match_mask.argmax(axis=0) has_match = match_mask.any(axis=0) df1_valid.loc[has_match, 'MAKE'] = make_arr[match_indices[has_match]] # 5. 将匹配结果合并回原df1 df1 = df1.merge(df1_valid[['brand', 'product_line', 'size', 'MAKE']], on=['brand', 'product_line', 'size'], how='left')
注:若匹配逻辑是df2的列包含于df1的列,只需调换
np.char.contains的两个参数位置。
方案二:apply结合矢量化匹配(更简洁)
通过apply对有效行批量处理,内部用矢量化的str.contains生成匹配条件,效率远高于逐行循环:
import pandas as pd # 1. 筛选有效行 df1_valid = df1[df1['profile'].notna()].copy() # 2. 定义匹配函数:传入df1单行,返回对应MAKE值 def get_make(row): mask = ( df2['NAME'].str.contains(row['brand']) & df2['PRODUCT_LINE'].str.contains(row['product_line']) & df2['SIZE'].str.contains(row['size']) ) return df2.loc[mask, 'MAKE'].iloc[0] if mask.any() else pd.NA # 3. 批量应用函数(内部为矢量化操作,性能优于逐行循环) df1_valid['MAKE'] = df1_valid.apply(get_make, axis=1) # 4. 合并结果回原df1 df1 = df1.merge(df1_valid[['brand', 'product_line', 'size', 'MAKE']], on=['brand', 'product_line', 'size'], how='left')
性能优化补充
- 若df2数据量极大,可先对匹配列建立TF-IDF索引,通过余弦相似度快速缩小匹配范围,进一步提升效率。
- 若存在多对多匹配,可按需调整逻辑(如返回所有匹配值的集合、取出现频率最高的MAKE等)。
内容的提问来源于stack exchange,提问作者SunAns
相关产品推荐
相关产品推荐

