百万级记录模糊匹配运行过慢,寻求性能优化方案
百万级数据模糊匹配优化方案
原代码性能瓶颈分析
你当前的代码使用fuzzywuzzy的process.extract循环匹配,本质是**O(n*m)**的时间复杂度——每一条co_zip22数据都要和整个co_zip23列做全量匹配。当数据量达到百万级时,总计算量突破1e12次,这是导致运行多天仍未完成的核心原因。
优化方案
以下是针对该场景的高效优化手段,按优先级排序:
1. 替换为更快的模糊匹配库:RapidFuzz
RapidFuzz是fuzzywuzzy的C++重写版本,速度比原生fuzzywuzzy快50-100倍,API兼容度极高,无需大幅修改代码逻辑。
代码示例:
from rapidfuzz import process, fuzz import pandas as pd # 定义匹配函数 def get_top_similarity(x, candidates): match_result = process.extractOne(x, candidates, scorer=fuzz.ratio) return match_result[1] if match_result else 0 # 批量计算相似度 df['similarity'] = df['co_zip22'].apply(get_top_similarity, candidates=df['co_zip23'].tolist())
2. 按邮编预分组,缩小匹配范围
co_zip是公司名+邮编的组合键,邮编是精确匹配项——同一公司的2022/2023记录邮编大概率一致。先按邮编分组,仅在同邮编的候选集中做模糊匹配,能把单条数据的匹配范围从百万级压缩到几百/几千级,性能提升显著。
代码示例(假设邮编是co_zip的最后5位,可根据实际格式调整):
from rapidfuzz import process, fuzz import pandas as pd # 拆分邮编列 df['zip_22'] = df['co_zip22'].str[-5:] df['zip_23'] = df['co_zip23'].str[-5:] # 构建「邮编→对应co_zip23候选集」的映射字典 zip_candidate_map = df.groupby('zip_23')['co_zip23'].apply(list).to_dict() # 仅在同邮编的候选集中匹配 def get_similarity_by_zip(x): current_zip = x[-5:] candidates = zip_candidate_map.get(current_zip, []) if not candidates: return 0 match_result = process.extractOne(x, candidates, scorer=fuzz.ratio) return match_result[1] if match_result else 0 df['similarity'] = df['co_zip22'].apply(get_similarity_by_zip)
3. 进一步加速:使用向量化/并行处理
如果数据量仍超大,可结合swifter库实现自动并行化的apply操作,进一步缩短运行时间。
swifter加速示例:
import swifter df['similarity'] = df['co_zip22'].swifter.apply(get_similarity_by_zip)
内容的提问来源于stack exchange,提问作者user22600865
相关产品推荐
相关产品推荐

