You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于姓名包含关系合并格式各异的Pandas DataFrame?

高效合并含复杂姓名列的DataFrame方案

针对你提出的合并需求,这里提供一套分步解决方案,既解决and/&分隔的多姓名问题,也能实现基于姓氏匹配的合并:

1. 拆分多姓名条目

首先把df2中用and或&分隔的姓名拆分成单独行,让每个行对应一个独立姓名,解决nameparser无法处理多姓名的问题:

import pandas as pd
import re

# 原始数据初始化
data1 = [['Anna','Tessmann',10], ['Ben','Fachmann',20], ['John','Smith',10]]
df1 = pd.DataFrame(data1, columns=['FirstName','LastName','Info1'])

data2 = [['Ben Fachmann',30], ['School AAA',40], ['John and Melissa Smith',50], ['Bob & Anna Tessmann',20]]
df2= pd.DataFrame(data2, columns=['Name','Info2'])

# 用正则拆分and/&分隔的姓名,处理前后空格
df2['split_names'] = df2['Name'].str.split(r'\s+(?:and|&)\s+')
# 拆分后展开为多行,每个姓名对应原Info2值
df2_exploded = df2.explode('split_names').reset_index(drop=True)

2. 基于姓氏匹配合并

方案A:快速模糊匹配(仅姓氏)

如果只需要基于「df2姓名包含df1姓氏」的规则,用交叉连接+过滤的方式简单直接:

# 交叉连接两个DataFrame,然后过滤匹配项
cross_join = df1.merge(df2_exploded, how='cross')
matched = cross_join[cross_join['split_names'].str.contains(cross_join['LastName'], case=False)]

# 整理最终结果,去重后保留关键列
final_result = matched[['FirstName', 'LastName', 'Info1', 'Name', 'Info2']].drop_duplicates()

方案B:高效精确匹配(完整姓氏单词)

如果数据量较大,交叉连接效率偏低,可改用正则提取姓氏后合并,同时避免部分匹配(比如防止"Smithson"被误判为包含"Smith"):

# 构建完整姓氏的正则匹配模式
last_name_regex = r'\b(' + '|'.join(df1['LastName'].tolist()) + r')\b'
# 从拆分后的姓名中提取匹配的姓氏
df2_exploded['matched_lastname'] = df2_exploded['split_names'].str.extract(last_name_regex, flags=re.IGNORECASE)

# 基于提取的姓氏和df1合并
final_result = df2_exploded.dropna(subset=['matched_lastname']).merge(
    df1, left_on='matched_lastname', right_on='LastName', how='left'
)[['FirstName', 'LastName', 'Info1', 'Name', 'Info2']]

方案C:名+姓精确匹配(可选)

如果需要更严格的名+姓匹配,拆分后可以用nameparser解析单个姓名,再和df1的名、姓对应:

from nameparser import HumanName

# 解析拆分后的单个姓名
df2_exploded['parsed_name'] = df2_exploded['split_names'].apply(HumanName)
df2_exploded['parsed_first'] = df2_exploded['parsed_name'].apply(lambda x: x.first)
df2_exploded['parsed_last'] = df2_exploded['parsed_name'].apply(lambda x: x.last)

# 基于名+姓精确合并
final_result = df2_exploded.merge(
    df1, 
    left_on=['parsed_first', 'parsed_last'], 
    right_on=['FirstName', 'LastName'], 
    how='inner'
)[['FirstName', 'LastName', 'Info1', 'Name', 'Info2']]

结果说明

  • 无关内容(如"School AAA")因不包含df1中的任何姓氏,会被自动过滤
  • 多姓名条目拆分后,每个姓名会单独和df1匹配,确保不遗漏有效关联
  • 三种方案可根据数据规模和匹配精度需求选择

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:15:12