大数据量下基于Fuzzy Wuzzy的DataFrame模糊匹配过滤优化咨询
优化模糊匹配过滤的高效方案
原函数在大数据集下速度慢的核心原因有两个:
iterrows()遍历DataFrame的效率极低,远不如向量化操作或apply();- 每条地址都要和匹配列表中所有元素计算相似度,时间复杂度为O(N*M)(N是DataFrame行数,M是匹配列表长度),数据量上去后计算量陡增。
下面是针对性的优化方案:
1. 先安装依赖加速库
默认的fuzzywuzzy是纯Python实现,速度很慢。安装python-Levenshtein(C扩展)可以让相似度计算速度提升10-100倍:
pip install python-Levenshtein fuzzywuzzy
或者直接用更快的替代库rapidfuzz(API和fuzzywuzzy兼容,性能更优):
pip install rapidfuzz pandas
2. 预处理地址文本
先标准化地址格式,减少无效计算同时提升匹配精度:
import pandas as pd from rapidfuzz import fuzz, process def preprocess_address(address): # 转小写、去空格、替换常见后缀 addr = str(address).lower().strip() addr = addr.replace(" st ", " street ") addr = addr.replace(" rd ", " road ") addr = addr.replace(" ave ", " avenue ") # 可根据需求添加更多标准化规则 return addr
3. 高效批量匹配实现
方案A:用rapidfuzz的批量匹配+pandas.apply
利用process.extractOne直接获取最高相似度,避免手动循环匹配列表:
def fuzzy_match_filter_optimized(data_frame, match_list): # 预处理匹配列表 processed_match = [preprocess_address(addr) for addr in match_list] # 定义批量匹配函数 def get_max_similarity(address): processed_addr = preprocess_address(address) # 获取最高相似度得分 if not processed_addr: return 0 result = process.extractOne(processed_addr, processed_match, scorer=fuzz.ratio) return result[1] if result else 0 # 向量化计算相似度 data_frame['max_similarity'] = data_frame['address'].apply(get_max_similarity) # 过滤并清理结果 filtered_df = data_frame[data_frame['max_similarity'] < 90].drop(columns=['max_similarity']) filtered_df.reset_index(drop=True, inplace=True) return filtered_df
方案B:先做快速过滤减少计算量
如果匹配列表有规律,可以先通过关键词/子串快速排除大概率匹配的地址,再对剩余地址做模糊匹配:
def fuzzy_match_filter_fast(data_frame, match_list): processed_match = [preprocess_address(addr) for addr in match_list] match_keywords = set() for addr in processed_match: match_keywords.update(addr.split()) # 第一步:快速过滤包含匹配关键词的地址(可根据需求调整规则) def has_match_keyword(address): processed_addr = preprocess_address(address) return any(key in processed_addr for key in match_keywords) # 先标记需要做模糊匹配的行 data_frame['need_fuzzy'] = ~data_frame['address'].apply(has_match_keyword) # 对需要模糊匹配的行计算相似度 def get_similarity(address): processed_addr = preprocess_address(address) result = process.extractOne(processed_addr, processed_match, scorer=fuzz.ratio) return result[1] if result else 0 data_frame.loc[data_frame['need_fuzzy'], 'max_similarity'] = data_frame.loc[data_frame['need_fuzzy'], 'address'].apply(get_similarity) # 未做模糊匹配的行默认相似度为100(视为匹配) data_frame['max_similarity'] = data_frame['max_similarity'].fillna(100) # 过滤结果 filtered_df = data_frame[data_frame['max_similarity'] < 90].drop(columns=['need_fuzzy', 'max_similarity']) filtered_df.reset_index(drop=True, inplace=True) return filtered_df
4. 极端大数据量的进阶优化
如果数据量超过百万级,可以考虑:
- 用
Dask代替pandas做分布式计算; - 构建n-gram索引(比如自定义分组逻辑),将地址按n-gram分组,只和同组的匹配列表元素计算相似度;
- 用近似字符串匹配的哈希算法(比如MinHash)先筛选候选集,再做精确模糊匹配。
内容的提问来源于stack exchange,提问作者mcolella
相关产品推荐
相关产品推荐

