对比两个DataFrame列表并输出差异:精度与代码优化问题
解决方案
1. 浮点数精度问题解决
- 确保round操作生效:你之前的
banks.round(1)或apply(lambda x:round(x,2))未修改原DataFrame,因为这些方法默认返回新对象,不会原地修改。必须将结果重新赋值:# 对整个DataFrame保留2位小数 df = df.round(2) # 或对指定列单独操作 df['target_col'] = df['target_col'].round(2) - 对比时忽略微小精度差:不要直接用
df1 == df2判断相等,改用numpy.isclose设置合理容差,过滤极小数值差异:
复制到Excel仍显示原值的问题,本质是之前的round操作未真正修改DataFrame,按上述赋值方式处理后,数值会被实际修改,复制到Excel就会显示保留小数后的结果。import numpy as np # 生成差异掩码,容差可根据需求调整 diff_mask = ~np.isclose(df1, df2, rtol=1e-8, atol=1e-10) # 提取真实差异的位置 diffs = df1[diff_mask].dropna(how='all').join(df2[diff_mask].dropna(how='all'), lsuffix='_left', rsuffix='_right')
2. 简化代码:直接遍历DataFrame列表对比
无需将列表中的DataFrame转为全局变量,用zip函数同时遍历两个列表的对应元素即可:
# 假设list1和list2是两个目录读取生成的DataFrame列表 for idx, (df_left, df_right) in enumerate(zip(list1, list2), 1): print(f"对比第{idx}组DataFrame") # 执行删列、保留小数、索引+1操作 df_left = df_left.drop(columns=['col_to_drop']).round(2) df_left.index = df_left.index + 1 df_right = df_right.drop(columns=['col_to_drop']).round(2) df_right.index = df_right.index + 1 # 执行差异对比逻辑 diff_mask = ~np.isclose(df_left, df_right, rtol=1e-8, atol=1e-10) diff_result = df_left[diff_mask].dropna(how='all').join(df_right[diff_mask].dropna(how='all'), lsuffix='_left', rsuffix='_right') # 输出带行列号的结果 print(diff_result)
3. 过滤假阳性差异,仅保留真实差异
即使指定了dtype='float',浮点数的二进制存储仍可能产生微小误差,继续用np.isclose的掩码过滤:
# 生成差异掩码 diff_mask = ~np.isclose(df1, df2, rtol=1e-8, atol=1e-10) # 筛选至少有一个真实差异的行和列 diff_rows = diff_mask.any(axis=1) diff_cols = diff_mask.any(axis=0) # 提取仅包含真实差异的DataFrame true_diff = df1.loc[diff_rows, diff_cols].join(df2.loc[diff_rows, diff_cols], lsuffix='_left', rsuffix='_right') # 输出结果 print(true_diff)
这样就能排除浮点数精度导致的假阳性差异,仅保留真正不同的(3,2)结果。
内容的提问来源于stack exchange,提问作者WX1505
相关产品推荐
相关产品推荐

