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

如何判断dataframe中含部分重叠信息的两行是否为相同/相似记录

同地址脏姓名数据匹配解决方案

前置预处理步骤

首先对全量数据做统一归一化处理,降低后续匹配误判率:

  • 新增norm_last字段:对Last Name做归一化,统一转小写、去除特殊符号/常用称谓后缀(Jr./Sr./罗马数字后缀等)、去除前后空格
  • 拆分First Name字段,新增两个衍生字段:
    • main_first:First Name按空格拆分后的第一个片段,做与上述相同的归一化处理
    • middle_name_list:First Name拆分后除第一个片段外的剩余片段列表,无中间名则为空列表

两类匹配问题判定规则

第一类:含中间名的行匹配

同一地址分组下的两条记录,同时满足以下条件即可判定为同一人:

  • 两条记录的norm_last完全相等
  • 其中一条记录的First Name长度更短,且其完整main_first与另一条记录的main_first完全相等

匹配示例:First Name=James Agnew, Last Name=Bond 和 First Name=James, Last Name=Bond 符合该类匹配规则,合并时可保留更长的全量姓名字段作为标准值。

第二类:缩略名匹配

同一地址分组下的两条记录,同时满足以下基础条件后,满足任意一个模糊匹配规则即可判定为同一人:

  • 基础条件:两条记录的norm_last完全相等
  • 模糊匹配规则(二选一即可):
    • 前缀匹配:较短的main_first所有字符与较长的main_first的前N位完全一致,N取较短名的长度,且要求短名长度≥3,避免单/双字母的误匹配
    • 常用缩略映射匹配:提前预制常用英文名-缩略/昵称映射表,两个main_first属于同一标准名的不同表达
    • (可选补充规则)两个main_first的莱文斯坦编辑距离≤2,覆盖少量拼写错误场景

注意:如果业务对匹配准确率要求极高,可关闭编辑距离补充规则,仅保留前缀匹配+预制映射表规则,可大幅降低误判概率

Pandas 场景实现参考

因为已按地址分组且每组仅2-3条记录,直接做组内两两比对即可,计算成本极低:

import pandas as pd
from Levenshtein import distance

# 姓名归一化函数
def normalize_name(s: str) -> str:
    s = s.lower().strip()
    # 清理特殊符号和常见后缀
    for remove_str in ['.', ',', 'jr', 'sr', 'iii', 'ii', '-']:
        s = s.replace(remove_str, '')
    return s.strip()

# 预处理生成衍生字段
df['norm_last'] = df['Last Name'].apply(normalize_name)
df['first_split'] = df['First Name'].apply(lambda x: [normalize_name(p) for p in x.split() if p.strip()])
df['main_first'] = df['first_split'].str[0]

# 按地址分组后匹配,匹配成功的记录标记相同的person_id
df['person_id'] = None
current_id = 1

# address为你的地址分组字段名,可根据实际表结构修改
for addr, group in df.groupby('address'):
    records = group.to_dict('records')
    matched = set()
    for i in range(len(records)):
        if i in matched:
            continue
        # 标记当前未匹配记录的id
        df.loc[records[i]['index'], 'person_id'] = current_id
        matched.add(i)
        # 和组内其他记录比对
        for j in range(i+1, len(records)):
            if j in matched:
                continue
            r1, r2 = records[i], records[j]
            # 姓氏不一致直接跳过
            if r1['norm_last'] != r2['norm_last']:
                continue
            # 第一类匹配判定
            min_len = min(len(r1['main_first']), len(r2['main_first']))
            if r1['main_first'][:min_len] == r2['main_first'][:min_len] and (len(r1['first_split'])>1 or len(r2['first_split'])>1):
                df.loc[r2['index'], 'person_id'] = current_id
                matched.add(j)
                continue
            # 第二类匹配判定
            if (r1['main_first'] == r2['main_first'][:min_len] and min_len >=3) or distance(r1['main_first'], r2['main_first']) <=2:
                df.loc[r2['index'], 'person_id'] = current_id
                matched.add(j)
        current_id +=1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:24:03