如何并行处理同名键对应DataFrame?匹配姓氏列最高Levenshtein距离
解决同键DataFrame的Levenshtein匹配并行处理问题
问题分析
你当前的代码核心问题有两个:一是嵌套循环遍历了两个字典的所有键组合,会生成9个配对任务(远多于你需要的3组同键配对);二是后续通过列名反向推导键的逻辑完全不可靠,很容易出现匹配错误。另外,Pandas DataFrame是可变对象,多线程中直接传递修改可能引发线程安全问题。
修正后的实现方案
核心思路
- 只处理两个字典共同键对应的DataFrame对(A-A、B-B、C-C)
- 单独封装处理函数,操作DataFrame副本避免原数据被污染
- 用
ThreadPoolExecutor提交精准配对的任务,直接通过返回值更新原字典
完整代码示例
首先安装依赖库:
pip install python-Levenshtein
Python代码实现:
import pandas as pd import Levenshtein from concurrent.futures import ThreadPoolExecutor # 处理单组同键DataFrame的函数 def process_matching(key, left_df, right_df): # 复制原DataFrame,避免多线程修改原数据 processed_df = left_df.copy() # 提前提取右侧姓名列表,减少循环内重复IO right_names = right_df['Last_Name'].tolist() # 为单个姓名找到Levenshtein距离最小的匹配项 def get_best_match(name): if pd.isna(name): return None # 计算当前姓名与右侧所有姓名的编辑距离 distances = [Levenshtein.distance(name, r_name) for r_name in right_names] # 取距离最小的姓名作为匹配结果 best_idx = distances.index(min(distances)) return right_names[best_idx] # 生成Match字段 processed_df['Match'] = processed_df['Last_Name'].apply(get_best_match) # 返回键和处理后的DataFrame,方便后续更新字典 return key, processed_df # 替换为你的实际数据 df1 = pd.DataFrame({'Last_Name': ['Smith', 'Johnson', 'Williams']}) df2 = pd.DataFrame({'Last_Name': ['Brown', 'Jones', 'Miller']}) df3 = pd.DataFrame({'Last_Name': ['Davis', 'Garcia', 'Rodriguez']}) df4 = pd.DataFrame({'Last_Name': ['Smyth', 'Johnsson', 'Williamson']}) df5 = pd.DataFrame({'Last_Name': ['Browne', 'Jone', 'Millar']}) df6 = pd.DataFrame({'Last_Name': ['Davies', 'Garcia', 'Rodrigez']}) dict1 = {"A": df1, "B": df2, "C": df3} dict2 = {"A": df4, "B": df5, "C": df6} # 并行处理同键配对 with ThreadPoolExecutor(max_workers=3) as executor: # 仅提交同键配对任务 futures = [ executor.submit(process_matching, key, dict1[key], dict2[key]) for key in dict1 if key in dict2 ] # 收集结果并更新dict1 for future in futures: key, result_df = future.result() dict1[key] = result_df # 验证输出 for key, df in dict1.items(): print(f"=== {key} 处理结果 ===") print(df)
关键优化点
- 精准配对:直接遍历共同键,确保只处理需要的3组数据,避免无效计算
- 线程安全:操作DataFrame副本,防止多线程同时修改原数据引发异常
- 逻辑清晰:函数直接返回键和处理后的DataFrame,无需通过列名猜测键值
- 效率提升:提前提取右侧姓名列表,避免在
apply循环中重复读取DataFrame列
内容的提问来源于stack exchange,提问作者Vinayak
相关产品推荐
相关产品推荐

