在大文件上应用FuzzyLogic时遇内存不足问题求助
解决FuzzyLogic处理大数据集时的内存不足问题
我太懂这种崩溃感了——小数据集跑起来顺风顺水,一搞大数据就爆内存,还弹出"Low memory Unable to create 6.6GB array"的提示。你的核心问题在于双重循环全量比对带来的巨量计算和内存开销,咱们一步步来优化,把这个问题解决掉。
先聊聊原代码的问题
- 你写的双重循环
for exp in exception_list套for orig in original_list,时间复杂度是O(n*m),当n和m都是几万甚至几十万级别的时候,不仅慢到离谱,中间生成的临时计算数据会直接把内存撑爆 - 手动调用fuzz的三个方法,会重复计算字符串的相似度,造成冗余开销
- difflib.get_close_matches每次都会遍历整个original_list,进一步加重内存负担
优化方案1:用FuzzyWuzzy的process.extractOne替代手动循环
FuzzyWuzzy的process模块内置了优化的匹配逻辑,extractOne会直接返回最匹配的结果,不需要你手动遍历整个列表,还能帮你减少重复计算。
修改后的核心代码:
from fuzzywuzzy import fuzz, process import pandas as pd # 读取数据的逻辑不变 df_To_beMatched = pd.read_excel('Vendor_file.xlsx', usecols=["VENDOR_NAME"]) df_To_beMatched['VENDOR_NAME'] = df_To_beMatched['VENDOR_NAME'].fillna('') original_list = df_To_beMatched['VENDOR_NAME'].tolist() df_exceptionlist = pd.read_excel('Exceptionfile.xlsx', usecols=["Entity_Name"]) df_exceptionlist['Entity_Name'] = df_exceptionlist['Entity_Name'].fillna('') exception_list = df_exceptionlist['Entity_Name'].tolist() result = [] for exp in exception_list: # 直接获取最匹配的结果,指定用token_set_ratio做评分 match, token_score, _ = process.extractOne(exp, original_list, scorer=fuzz.token_set_ratio) # 再补充检查另外两个阈值 ratio_score = fuzz.ratio(exp, match) partial_score = fuzz.partial_ratio(exp, match) if token_score > 75 and ratio_score > 75 and partial_score > 85: result.append({ 'Entity_Name': exp, 'VENDOR_NAME': match, 'Ratio': ratio_score, 'Token': token_score, 'Status': 'Match' }) # 保存结果 fuzzy_df = pd.DataFrame(result) fuzzy_df.to_csv('FuzzyLogic_Results.csv', index=False)
优化方案2:分块处理数据集(内存救星)
如果你的数据集大到连加载到内存都困难,那就把数据切成小块,每次只处理一小块,处理完就释放内存,绝对不会爆内存。
示例代码:
from fuzzywuzzy import fuzz, process import pandas as pd def process_chunk(chunk_data, exception_list): chunk_results = [] for exp in exception_list: match, token_score, _ = process.extractOne(exp, chunk_data, scorer=fuzz.token_set_ratio) ratio_score = fuzz.ratio(exp, match) partial_score = fuzz.partial_ratio(exp, match) if token_score > 75 and ratio_score > 75 and partial_score > 85: chunk_results.append({ 'Entity_Name': exp, 'VENDOR_NAME': match, 'Ratio': ratio_score, 'Token': token_score, 'Status': 'Match' }) return chunk_results # 分块读取原始数据,chunk_size根据你的内存情况调整,比如设为1000或5000 chunk_size = 1000 final_result = [] # 逐块处理 for chunk in pd.read_excel('Vendor_file.xlsx', usecols=["VENDOR_NAME"], chunksize=chunk_size): chunk['VENDOR_NAME'] = chunk['VENDOR_NAME'].fillna('') chunk_list = chunk['VENDOR_NAME'].tolist() chunk_result = process_chunk(chunk_list, exception_list) final_result.extend(chunk_result) # 保存结果 fuzzy_df = pd.DataFrame(final_result) fuzzy_df.to_csv('FuzzyLogic_Results.csv', index=False)
优化方案3:换成RapidFuzz(速度+内存双优化)
FuzzyWuzzy其实是基于RapidFuzz的旧封装,RapidFuzz用C++实现,速度快好几倍,内存占用还更低,API和FuzzyWuzzy几乎完全兼容,直接替换就行。
先安装:
pip install rapidfuzz
然后把导入部分改成:
from rapidfuzz import fuzz, process
其他代码完全不用改,你会发现不仅内存占用降下来了,运行速度也快了一大截。
优化方案4:给difflib瘦个身
如果你还需要保留difflib的结果,记得给get_close_matches加个n参数限制返回的匹配数量,避免生成太多结果占内存:
# 只返回前3个最匹配的结果,你可以根据需求调整 difflib_result = difflib.get_close_matches(to_delete, original_list, n=3) matches = "^".join(difflib_result) result_difflib.append({'Entity_Name': to_delete, 'Matches': matches})
如果不需要这部分结果,直接删掉能进一步减少内存消耗。
这些方法可以单独用,也可以组合起来(比如RapidFuzz+分块处理),应该能完美解决你的内存问题。
内容的提问来源于stack exchange,提问作者Python Explorer
相关产品推荐
相关产品推荐

