You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas df.drop_duplicates()无效,浮点精度致重复行无法删除

Pandas drop_duplicates 无效:浮点数精度导致的"伪重复"问题

这是典型的浮点数精度误差问题——虽然表面显示都是3542.87,但实际存储的是带有微小尾差的浮点值(比如3542.87、3542.8700000000003、3542.870000000001),这些差异肉眼不可见,但会让drop_duplicates()判定为不同行。

一、现有数据的清理方案

1. 四舍五入到指定小数位

针对金额数据,直接保留两位小数即可解决问题:

# 对solde列四舍五入到两位小数
df['solde'] = df['solde'].round(2)
# 执行去重
df_cleaned = df.drop_duplicates(subset=['Date', 'Libellé', 'Montant', 'solde'], keep='first')

2. 模糊匹配去重(自定义精度)

如果需要更灵活的误差范围控制,用numpy.isclose实现模糊分组:

import numpy as np

def merge_close_solde(group):
    # 以组内第一个solde值为基准,将所有接近的数值统一
    base_val = group['solde'].iloc[0]
    group['solde'] = np.where(np.isclose(group['solde'], base_val, atol=1e-6), base_val, group['solde'])
    return group

# 分组统一数值后再去重
df_cleaned = df.groupby(['Date', 'Libellé', 'Montant'], group_keys=False).apply(merge_close_solde)
df_cleaned = df_cleaned.drop_duplicates()

3. 用Decimal类型实现精确运算

如果要彻底杜绝浮点误差,将金额列转换为decimal.Decimal类型(支持精确十进制计算):

from decimal import Decimal, getcontext

# 设置精度为两位小数,适配金额场景
getcontext().prec = 2

# 转换solde和Montant列
df['solde'] = df['solde'].apply(lambda x: Decimal(str(x)).quantize(Decimal('0.00')))
df['Montant'] = df['Montant'].apply(lambda x: Decimal(str(x)).quantize(Decimal('0.00')))

# 此时去重可正常执行
df_cleaned = df.drop_duplicates()

二、预防未来出现此类问题的措施

  • 导入阶段处理:读取数据时直接控制精度,避免浮点误差引入:
    # 读取CSV时直接对金额列四舍五入
    df = pd.read_csv('your_data.csv', converters={
        'solde': lambda x: round(float(x), 2),
        'Montant': lambda x: round(float(x), 2)
    })
    
  • 避免运算累积误差:如果数据是计算生成的,每一步运算后都进行精度截断(比如四舍五入),防止微小误差累积放大。
  • 整数存储金额:将金额转换为分(乘以100),用整数类型存储,彻底消除小数运算的精度问题:
    # 转换为分存储,用Int64类型支持空值
    df['solde_cents'] = (df['solde'] * 100).astype('Int64')
    df['Montant_cents'] = (df['Montant'] * 100).astype('Int64')
    

内容的提问来源于stack exchange,提问作者fran6

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 22:47:03