如何在Pandas中利用另一Series实现str.contains子串匹配?
Pandas中基于另一Series实现子串匹配(替代精确匹配)
问题场景
现有如下DataFrame,LName是包含业务标识的长字符串,RName是用|分隔的候选匹配串,需要从RName的候选中找出与LName存在关键词匹配的项(对应Expected列结果)。原有的精确匹配方法(直接对比字符串相等)无法满足需求,需要实现类似str.contains的子串/关键词匹配逻辑。
示例数据:
import pandas as pd import numpy as np df = pd.DataFrame({'LName': ['AT-D81CGG3-RED-STORAGE-GEN4.2', 'AT-Z111AC5-RED-STORAGEUTILITY-GEN4.2'], 'RName': ['AT_Utility_Gen4_2|AT_Storage_Gen4_2', 'ATAT_Utility_Gen4_2|AT_Storage_Gen4_2'], 'Expected': ['AT_Storage_Gen4_2', 'AT_Utility_Gen4_2']})
原精确匹配代码(无效):
# 仅做精确字符串相等判断,无法实现子串匹配 df['RName'].str.split('|', expand=True).eq(df['LName'], axis=0).any(1).astype(np.int8)
解决方案1:逐行自定义匹配(直观易读)
通过apply逐行处理,提取候选串中的关键词,检查是否在LName中存在:
def find_matching_candidate(row): lname_upper = row['LName'].upper() candidates = row['RName'].split('|') for cand in candidates: # 提取候选串的关键词(去掉开头的前缀部分) cand_keywords = cand.upper().split('_')[1:] # 检查所有关键词是否都在LName中(确保匹配核心业务标识) if all(key in lname_upper for key in cand_keywords): return cand return None # 无匹配项时返回None # 生成匹配结果 df['Matched'] = df.apply(find_matching_candidate, axis=1)
运行后Matched列将与Expected列结果完全一致。
解决方案2:向量化拆分匹配(高效适用于大数据)
避免apply的逐行循环,通过拆分候选串为多行、批量匹配后合并的方式提升效率:
# 保留原索引,将RName拆分为多行候选 expanded_df = df.assign(RName=df['RName'].str.split('|')).explode('RName') # 批量生成匹配标记:检查候选关键词是否在LName中 expanded_df['is_match'] = expanded_df.apply( lambda x: all(key in x['LName'].upper() for key in x['RName'].upper().split('_')[1:]), axis=1 ) # 按原索引分组,取第一个匹配的候选串 matched_results = expanded_df[expanded_df['is_match']].groupby(expanded_df.index)['RName'].first() # 合并回原DataFrame df['Matched'] = matched_results
逻辑说明
两种方案的核心逻辑一致:
- 统一转为大写,避免大小写敏感问题
- 提取候选串的核心关键词(去掉前缀如
AT_/ATAT_) - 验证关键词是否全部存在于
LName中,确保匹配的是业务核心标识而非前缀
内容的提问来源于stack exchange,提问作者John Stud
相关产品推荐
相关产品推荐

