PySpark:如何基于字符串包含关系关联两个无键DataFrame
问题描述
给定两个DataFrame:
df1
| Name1 | Colour |
|---|---|
| Lisa | ('blue','yellow') |
| Bart | ('pink', 'yellow') |
| Homer | ('green', 'black') |
| Maggie | ('yellow','orange','blue') |
df2
| Name2 | Age |
|---|---|
| Lisa S. | 5 |
| Bart Simpsons | 8 |
| Bob | 10 |
| Ben | 30 |
需要实现当df2的Name2字段包含df1的Name1字段字符串时,将两表关联,最终得到如下预期输出:
| Name2 | Age | Name1 | Colour |
|---|---|---|---|
| Lisa S. | 5 | Lisa | ('blue','yellow') |
| Bart Simpsons | 8 | Bart | ('pink', 'yellow') |
常规等值关联因无匹配键无法实现,可通过以下两种方法完成条件关联:
解决方案
方法1:笛卡尔积+条件筛选(适合小数据量)
先生成两表的全连接(笛卡尔积),再筛选符合Name2包含Name1条件的行:
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'Name1': ['Lisa', 'Bart', 'Homer', 'Maggie'], 'Colour': [('blue','yellow'), ('pink', 'yellow'), ('green', 'black'), ('yellow','orange','blue')] }) df2 = pd.DataFrame({ 'Name2': ['Lisa S.', 'Bart Simpsons', 'Bob', 'Ben'], 'Age': [5, 8, 10, 30] }) # 生成笛卡尔积 cross_join = df2.assign(key=1).merge(df1.assign(key=1), on='key').drop('key', axis=1) # 筛选符合条件的行 result = cross_join[cross_join.apply(lambda row: row['Name1'] in row['Name2'], axis=1)] # 调整列顺序匹配预期输出 result = result[['Name2', 'Age', 'Name1', 'Colour']] print(result)
方法2:逐行匹配(适合大数据量)
通过apply为df2的每一行匹配df1中符合条件的记录,避免生成全量笛卡尔积,效率更高:
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'Name1': ['Lisa', 'Bart', 'Homer', 'Maggie'], 'Colour': [('blue','yellow'), ('pink', 'yellow'), ('green', 'black'), ('yellow','orange','blue')] }) df2 = pd.DataFrame({ 'Name2': ['Lisa S.', 'Bart Simpsons', 'Bob', 'Ben'], 'Age': [5, 8, 10, 30] }) def find_match(row): # 查找df1中Name1包含在当前Name2中的记录 match_row = df1[df1['Name1'].apply(lambda x: x in row['Name2'])] if not match_row.empty: return pd.Series([match_row['Name1'].iloc[0], match_row['Colour'].iloc[0]]) return pd.Series([None, None]) # 添加匹配结果列 df2[['Name1', 'Colour']] = df2.apply(find_match, axis=1) # 过滤无匹配的行 result = df2.dropna(subset=['Name1']) print(result)
内容的提问来源于stack exchange,提问作者user4046073
相关产品推荐
相关产品推荐

