如何优雅计算同结构DataFrame各列匹配百分比(忽略NaN)
优雅实现DataFrame列匹配百分比计算
核心思路
用Pandas的向量化操作替代循环与apply,直接对整列做批量计算,既提升效率又简化逻辑。核心是先过滤真值数据集(df2)的NaN值,再计算匹配数与有效样本数的比值。
优化后的代码实现
import pandas as pd # 读取数据,保留原始类型(不转成str,避免把NaN变成字符串'nan') test_set = pd.read_excel(file_path) a_set = pd.read_excel(file2_path) # 按file_name合并两个数据集(保持与原逻辑一致的inner join) merged_df = a_set.merge(test_set, on='file_name', suffixes=('_x', '_y')) # 提取需要对比的字段(排除file_name) fields = [col for col in test_set.columns if col != 'file_name'] # 1. 计算真值数据集(_y列)每列的非NaN有效样本数 valid_counts = merged_df[[f"{field}_y" for field in fields]].notna().sum() # 2. 计算每列的匹配数:仅当真值非NaN时,对比两列小写后是否相等 match_mask = (merged_df[[f"{field}_x" for field in fields]].apply(lambda col: col.str.lower()) == merged_df[[f"{field}_y" for field in fields]].apply(lambda col: col.str.lower())) # 把真值为NaN的位置设为False(不参与计数) match_mask = match_mask.where(merged_df[[f"{field}_y" for field in fields]].notna(), False) matches = match_mask.sum() # 3. 计算匹配百分比,保留两位小数 match_percentages = (matches / valid_counts * 100).round(2) # 重置索引为原字段名 match_percentages.index = fields print(match_percentages)
代码说明
- 避免无效类型转换:不再将DataFrame强制转为
str,保留原始NaN,用notna()更精准判断空值。 - 向量化提升效率:用整列对比替代逐行
apply,处理大数据集时速度优势明显。 - 逻辑拆分清晰:分步骤计算有效样本数、匹配数、百分比,代码可读性更强。
- 结果直观对齐:将结果索引重置为原字段名,输出格式更符合需求。
示例验证
针对你给出的示例:
- 合并后
country_name_y的有效样本数为3,匹配数为2。 - 计算得
2/3*100≈66.67%,与预期完全一致。
内容的提问来源于stack exchange,提问作者sagi
相关产品推荐
相关产品推荐

