如何实现DataFrame列间部分字符串匹配并提取匹配值?
DataFrame列间部分字符串匹配与值提取
问题场景
我有两个各包含2列的DataFrame,需要将df1的A列与df2的C列进行部分字符串匹配,并提取对应的匹配值。
示例数据
df1:
| A | B |
|---|---|
| ABC PVT Ltd | 1FWE23 |
| Auxil Solutions | 22354 |
| Cambridge | 32684 |
| Stacking Ltd | 45368 |
| Ciscovt Ltd | 46485 |
| Samsung Ltd | 45346 |
| Nokia Ltd | 58446 |
df2:
| C | D |
|---|---|
| BTD | AAVV |
| Auxil Company | ASDC |
| Cambridge Univers | DECVD |
| The Stacking Pvt | DVVCA |
| Ciscovt brand | VDKMN |
| The Samsung Mobile | VDAVV |
| The Nokia Mobile | VFAD |
我之前尝试将df2的C列转成列表后与df1的A列对比,但没搞对部分匹配的逻辑,试的代码是:
dd= (df2['C'].str.upper()).unique().tolist() df1['New'] = (df1['A'].str.upper()).apply(lambda x: ''.join([part for part in dd if part in x]))
期望输出
| A | B | New |
|---|---|---|
| ABC PVT Ltd | 1FWE23 | |
| Auxil Solutions | 22354 | Auxil Company |
| Cambridge | 32684 | Cambridge Univers |
| Stacking Ltd | 45368 | The Stacking Pvt |
| Ciscovt Ltd | 46485 | Ciscovt brand |
| Samsung Ltd | 45346 | The Samsung Mobile |
| Nokia Ltd | 58446 | The Nokia Mobile |
解决方案
你的代码逻辑反了:你是检查df2的C列转大写后是否是df1A列转大写的子串,但实际需要的是df1A列中的核心关键词出现在df2的C列字符串中(比如"Auxil"在"Auxil Company"里)。以下是几种可行的实现方式:
方法1:调整apply的匹配逻辑
直接遍历df2的C列,检查df1的A值是否与C值存在单词级的重叠匹配:
df1['New'] = df1['A'].apply( lambda x: next( (c for c in df2['C'] if any(word in c for word in x.split())), '' ) )
- 逻辑:对df1的每个A值,按空格拆分单词,遍历df2的C列,返回第一个包含A值中任意单词的C值;无匹配则返回空字符串。
- 优点:无需额外依赖,逻辑简单直接。
方法2:正则表达式精准匹配
如果需要明确匹配核心词(比如去掉Ltd、Solutions这类后缀),可以用正则实现精准匹配:
# 提取df1 A列的核心词(去除常见后缀) df1['core_word'] = df1['A'].str.replace(r'\s+(Ltd|Solutions)$', '', regex=True) # 生成匹配核心词的正则模式 match_pattern = '|'.join(df1['core_word']) # 在df2中标记匹配的核心词 df2['matched_core'] = df2['C'].str.extract(f'({match_pattern})', expand=False) # 合并两个DataFrame,关联匹配结果 df1 = df1.merge(df2[['matched_core', 'C']], left_on='core_word', right_on='matched_core', how='left') # 整理最终列 df1['New'] = df1['C'].fillna('') df1.drop(columns=['core_word', 'matched_core', 'C'], inplace=True)
- 优点:避免误匹配,适合核心词明确的场景。
方法3:模糊匹配(适用于相似度较高的字符串)
如果字符串存在拼写差异但语义相近,可以用fuzzywuzzy库做模糊匹配:
from fuzzywuzzy import process df1['New'] = df1['A'].apply( lambda x: process.extractOne(x, df2['C'], score_cutoff=70)[0] if process.extractOne(x, df2['C'], score_cutoff=70) else '' )
- 说明:
score_cutoff=70表示匹配相似度超过70分才返回结果,可根据需求调整阈值。 - 依赖安装:执行
pip install fuzzywuzzy python-Levenshtein安装所需库。
内容的提问来源于stack exchange,提问作者Pravin
相关产品推荐
相关产品推荐

