如何按特定匹配规则合并两个Pandas DataFrame?
Pandas按匹配行数规则合并DataFrame
问题描述
现有两个Pandas DataFrame:
import pandas as pd df1 = pd.DataFrame({'keyword': ['Sox','Sox','Jays','D', 'Jays'], 'val':[1,2,3,4,5]}) df2 = pd.DataFrame({'name': ['a b c', 'Sox Red', 'Blue Jays White Sox'], 'city':[f'city-{i}' for i in [1,2,3]], 'info': [5, 6, 7]})
它们的结构如下:
>>> df1 keyword val 0 Sox 1 1 Sox 2 2 Jays 3 3 D 4 4 Jays 5 >>> df2 name city info 0 a b c city-1 5 1 Sox Red city-2 6 2 Blue Jays White Sox city-3 7
需要按以下规则合并:
- 对df1每行的
keyword,检查是否存在于df2的name字段中(可使用.str.contains) - 若恰好匹配df2的1行,则将该行df2的对应字段合并到df1中
- 若匹配0行或多行,则df2的对应字段填充NaN
期望结果:
keyword val name city info 0 Sox 1 NaN NaN NaN 1 Sox 2 NaN NaN NaN 2 Jays 3 Blue Jays White Sox city-3 7.0 3 D 4 NaN NaN NaN 4 Jays 5 Blue Jays White Sox city-3 7.0
实现方案
可以通过以下紧凑的代码实现需求:
import pandas as pd df1 = pd.DataFrame({'keyword': ['Sox','Sox','Jays','D', 'Jays'], 'val':[1,2,3,4,5]}) df2 = pd.DataFrame({'name': ['a b c', 'Sox Red', 'Blue Jays White Sox'], 'city':[f'city-{i}' for i in [1,2,3]], 'info': [5, 6, 7]}) # 1. 找出df2中每个name包含的所有keyword,展开成匹配对 matched_pairs = df2.assign( keywords=df2['name'].str.findall('|'.join(df1['keyword'].unique())) ).explode('keywords') # 2. 筛选出仅匹配df2一行的keyword,重命名列对齐df1 valid_matches = matched_pairs.groupby('keywords').filter( lambda x: len(x) == 1 ).rename(columns={'keywords': 'keyword'}) # 3. 左连接合并到df1,自动为不满足条件的行填充NaN result = df1.merge(valid_matches[['keyword', 'name', 'city', 'info']], on='keyword', how='left') print(result)
代码逻辑说明
str.findall:匹配每个name中包含的所有keyword,生成列表格式的匹配结果explode:将列表格式的匹配结果展开为一行一个匹配对,方便后续统计groupby.filter:筛选出在匹配对中仅出现一次的keyword(即只对应df2一行的keyword)merge(how='left'):以df1为基准左连接,自动为匹配0行或多行的keyword填充NaN
内容的提问来源于stack exchange,提问作者Vladimir Fokow
相关产品推荐
相关产品推荐

