如何高效匹配名称不一致的企业数据集?
企业名称匹配高效解决方案(针对专利诉讼事件研究数据集合并)
一、预处理:标准化企业名称(大幅降低模糊匹配噪音)
先统一名称格式,抹平大部分无意义差异,减少后续匹配的候选量:
- 统一大小写:全部转换为大写/小写,消除
Apple, INC.与Apple INC的大小写差异 - 清理标点符号:移除逗号、句号、连字符等,将
Apple, INC.转为APPLE INC - 标准化企业后缀:建立映射表统一常见后缀,比如
INC./INC/CORPORATION统一为CORP;LTD/LIMITED统一为LTD;OYJ/OY统一为OYJ - 过滤冗余通用词:移除
THE、GROUP、COMPANY这类高频无意义词(先做词频统计,仅移除出现次数极高的词,避免误删核心信息)
二、分层匹配策略(从精确到模糊,最小化人工介入)
1. 精确匹配(优先过滤完全匹配记录)
对预处理后的名称做精确匹配,直接匹配的记录无需人工核对,这部分能覆盖绝大多数格式修复后的匹配需求。
2. 核心关键词匹配(解决缩写/全称差异)
提取名称中的核心主体词,建立匹配逻辑:
- 预先整理行业常见缩写-全称映射表(比如
IBM对应International Business Machines Corporation) - 为黄金数据中的每个企业提取核心词(比如取去除后缀后的第一个名词),事件数据名称做同样处理后,通过核心词做精确匹配
- 示例:
Nokia Technologies提取核心词NOKIA,直接匹配黄金数据中的NOKIA OYJ
3. 优化后的模糊匹配(针对剩余难匹配记录)
放弃单一阈值,结合算法与行业特征:
- 选用Jaccard相似度(基于字符/词的交集/并集),比普通编辑距离更适合长名称,聚焦核心重合部分
- 分行业设置阈值:科技行业名称结构相似,阈值设为80%;传统行业名称差异大,设为75%
- 仅对核心词部分计算相似度,而非整个名称,避免非核心后缀干扰匹配结果
4. 子母公司关联匹配
- 建立子母公司映射库:手动整理行业知名企业的子母公司关系(从年报、工商信息提取),或通过规则识别:若事件数据名称包含母公司核心词+
Technologies/Solutions/Services等子公司常见后缀,自动关联到母公司 - 批量处理:对符合
[母公司核心词]+子公司后缀格式的名称,直接匹配对应母公司
三、Python工具实现(适配10万+数据量)
用pandas+rapidfuzz(比fuzzywuzzy更快)实现分层匹配:
1. 名称标准化函数
import re import pandas as pd from rapidfuzz import fuzz, process def normalize_name(name): if pd.isna(name): return "" # 统一大写 name = name.upper() # 移除标点 name = re.sub(r'[^\w\s]', '', name) # 标准化后缀 suffix_map = { r'\bINC\b': 'CORP', r'\bINCORPORATED\b': 'CORP', r'\bCORP\b': 'CORP', r'\bLTD\b': 'LTD', r'\bLIMITED\b': 'LTD', r'\bOYJ\b': 'OYJ', r'\bOY\b': 'OYJ' } for pattern, replace in suffix_map.items(): name = re.sub(pattern, replace, name) # 过滤冗余词 stop_words = {'THE', 'GROUP', 'COMPANY'} words = name.split() words = [word for word in words if word not in stop_words] return ' '.join(words)
2. 分层匹配流程
# 加载数据集 event_data = pd.read_csv('event_data.csv') gold_data = pd.read_csv('gold_data.csv') # 标准化名称 event_data['normalized_name'] = event_data['Plaintiff Name'].apply(normalize_name) gold_data['normalized_name'] = gold_data['Company Name'].apply(normalize_name) gold_data['core_word'] = gold_data['normalized_name'].str.split().str[0] # 1. 精确匹配 exact_matches = pd.merge(event_data, gold_data, on='normalized_name', how='left') matched = exact_matches[~exact_matches['Company ID'].isna()] unmatched = exact_matches[exact_matches['Company ID'].isna()].drop(columns=gold_data.columns.difference(['normalized_name'])) # 2. 核心词匹配 core_matches = pd.merge(unmatched, gold_data, left_on='core_word', right_on='core_word', how='left') core_matched = core_matches[~core_matches['Company ID'].isna()] unmatched = core_matches[core_matches['Company ID'].isna()].drop(columns=gold_data.columns.difference(['normalized_name', 'core_word'])) # 3. 模糊匹配(仅处理剩余未匹配记录) def fuzzy_match(row): candidates = gold_data[gold_data['core_word'] == row['core_word']]['normalized_name'] if row['core_word'] else gold_data['normalized_name'] if len(candidates) == 0: return pd.Series([None, None]) match, score = process.extractOne(row['normalized_name'], candidates, scorer=fuzz.Jaccard) if score >= 80: matched_row = gold_data[gold_data['normalized_name'] == match].iloc[0] return pd.Series([matched_row['Company ID'], matched_row['Company Name']]) else: return pd.Series([None, None]) unmatched[['Company ID', 'Company Name']] = unmatched.apply(fuzzy_match, axis=1) # 合并所有匹配结果 final_data = pd.concat([matched, core_matched, unmatched])
四、人工核对优化
- 仅对模糊匹配得分在70%-80%之间的记录做人工核对,得分低于70%的标记为“待确认”,后续单独处理
- 子母公司匹配的疑似记录,先批量关联后抽查10%验证,确认无误后批量生效
内容的提问来源于stack exchange,提问作者Hao Pan
相关产品推荐
相关产品推荐

