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

合并Pandas DataFrame时行丢失,匹配值存在却无法关联?

解决DataFrame合并行丢失的思路

核心问题:浮点数精度误差

你遇到的问题本质是浮点数的精度陷阱。虽然表面上df2['price'][0]显示为27.65,但实际存储的是一个接近27.65的近似值(比如27.649999999999996),直接用27.65 in df2['price']或者基于price列精确匹配时,会因为微小的精度差异导致匹配失败,进而丢失行。

具体排查与解决步骤

  • 验证浮点数精度问题
    执行以下代码查看price列的实际存储值:

    # 打印df2中price列的精确值
    print(df2['price'].apply(lambda x: format(x, '.20f')))
    

    你会看到类似27.64999999999999644729的结果,这就是直接匹配失败的原因。

  • 方法一:对浮点数进行四舍五入处理
    合并前对两个DataFrame的price列保留固定小数位(比如2位),消除精度差异:

    df1['price'] = df1['price'].round(2)
    df2['price'] = df2['price'].round(2)
    # 再执行合并
    master = pd.merge(df1, df2, on=['date', 'price', 'code'])
    
  • 方法二:使用近似匹配合并
    如果不想修改原始数据,可以使用merge_asof结合容差实现近似匹配(适用于数值列的近似关联):

    # 先按code和date排序(merge_asof要求输入已排序)
    df1_sorted = df1.sort_values(['code', 'date'])
    df2_sorted = df2.sort_values(['code', 'date'])
    # 设置price的匹配容差,比如0.001
    master = pd.merge_asof(df1_sorted, df2_sorted, 
                          on='date',
                          by=['code'],
                          tolerance={'price': 0.001},
                          direction='nearest')
    
  • 方法三:将浮点数转换为字符串(谨慎使用)
    把price列格式化为固定长度的字符串,避免精度问题:

    df1['price_str'] = df1['price'].apply(lambda x: f"{x:.2f}")
    df2['price_str'] = df2['price'].apply(lambda x: f"{x:.2f}")
    master = pd.merge(df1, df2, on=['date', 'price_str', 'code']).drop('price_str', axis=1)
    

额外验证步骤

  • 检查date列的隐式差异:虽然显示为字符串,但可能存在空格、时区标识等隐藏字符,可以用以下代码验证:
    # 检查date列的字符串长度是否一致
    print(df1['date'].str.len().unique())
    print(df2['date'].str.len().unique())
    # 去除可能的空格
    df1['date'] = df1['date'].str.strip()
    df2['date'] = df2['date'].str.strip()
    
  • 确认code列的一致性:虽然显示为int,但可能存在存储为object类型的情况(比如包含字符串格式的数字),可以用df1['code'].astype(str).equals(df2['code'].astype(str))验证。

内容的提问来源于stack exchange,提问作者fx-85

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:31:43