基于多列(含浮点列)模糊匹配DataFrame,查找主数据缺失记录
模糊匹配找出DataFrame中的缺失记录
针对你遇到的问题——无法用fuzzy_pandas实现需求,以下是几种可靠的解决方案:
方法1:结合fuzzywuzzy自定义模糊匹配逻辑
该方法灵活可控,能同时处理字符串模糊匹配和数值容差:
- 安装依赖包(未安装的话):
pip install fuzzywuzzy python-Levenshtein
- 核心代码:
import pandas as pd from fuzzywuzzy import fuzz, process # 示例数据(替换为你的实际DataFrame) Master_data_df = pd.DataFrame({ 'Client_Name': ['ABC Corp', 'XYZ Ltd', 'LMN Inc', 'PQR Group'], 'Transaction_Value': [100.05, 200.10, 300.00, 400.50], 'Other_Info': ['A', 'B', 'C', 'D'] }) My_records_df = pd.DataFrame({ 'Client_Name': ['ABC Corporation', 'XYZ Limited', 'PQR Grp'], 'Transaction_Value': [100.03, 200.12, 400.48], 'Other_Info': ['A', 'B', 'D'] }) # 配置匹配参数 NAME_MATCH_THRESHOLD = 80 # 字符串相似度阈值(0-100) VALUE_TOLERANCE = 0.05 # 数值允许的最大差值 def check_match(row, target_df): # 模糊匹配客户名称 best_match = process.extractOne(row['Client_Name'], target_df['Client_Name'], scorer=fuzz.token_sort_ratio) if not best_match: return False match_name, score = best_match[:2] if score < NAME_MATCH_THRESHOLD: return False # 检查交易值差异 match_value = target_df.loc[target_df['Client_Name'] == match_name, 'Transaction_Value'].values[0] return abs(row['Transaction_Value'] - match_value) <= VALUE_TOLERANCE # 标记主表中是否存在匹配记录 Master_data_df['has_match'] = Master_data_df.apply(check_match, target_df=My_records_df, axis=1) # 获取缺失记录(无匹配的行) missing_records = Master_data_df[~Master_data_df['has_match']].drop('has_match', axis=1) print("Master中未出现在My_records的记录:") print(missing_records)
方法2:用merge_asof处理数值 + 字符串二次过滤
如果交易值有顺序性,merge_asof是更高效的选择:
import pandas as pd from fuzzywuzzy import fuzz # 按交易值排序(merge_asof要求) master_sorted = Master_data_df.sort_values('Transaction_Value').reset_index(drop=True) my_sorted = My_records_df.sort_values('Transaction_Value').reset_index(drop=True) # 按数值容差匹配 merged = pd.merge_asof( master_sorted, my_sorted.add_suffix('_my'), on='Transaction_Value', tolerance=VALUE_TOLERANCE, direction='nearest' ) # 过滤字符串相似度不足的记录 merged['name_similarity'] = merged.apply( lambda x: fuzz.token_sort_ratio(x['Client_Name'], x['Client_Name_my']) if pd.notna(x['Client_Name_my']) else 0, axis=1 ) missing_records = merged[(merged['name_similarity'] < NAME_MATCH_THRESHOLD) | merged['Client_Name_my'].isna()] print(missing_records)
方法3:修复fuzzy_pandas的使用问题
如果你坚持用fuzzy_pandas,可以通过以下方式绕过join参数限制并解决空结果问题:
import fuzzy_pandas as fpd from fuzzywuzzy import fuzz def name_match(x, y): return fuzz.token_sort_ratio(x, y) >= NAME_MATCH_THRESHOLD def value_match(x, y): return abs(x - y) <= VALUE_TOLERANCE # 执行模糊匹配 matched = fpd.fuzzy_merge( Master_data_df, My_records_df, left_on=['Client_Name', 'Transaction_Value'], right_on=['Client_Name', 'Transaction_Value'], match_funcs=[name_match, value_match] ) # 获取主表中未匹配的行(通过索引判断) matched_master_indices = matched['index_left'].unique() missing_records = Master_data_df[~Master_data_df.index.isin(matched_master_indices)] print(missing_records)
以上方法都能帮你找出Master_data_df中未出现在My_records_df的记录,其中缺失记录会保留主表数据,未匹配的关联列会显示NaN。
内容的提问来源于stack exchange,提问作者sagardbhangale
相关产品推荐
相关产品推荐

