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

如何用另一DataFrame两列值(含近似匹配)过滤pandas DataFrame

Pandas实现ID精确匹配+数值近似匹配的过滤方案

问题背景

给定两个DataFrame,需要通过ID列精确匹配+**数值列近似匹配(处理舍入误差)**筛选df1的行,得到目标结果df3。

示例数据构造

首先还原示例中的两个DataFrame:

import pandas as pd

df1 = pd.DataFrame({
    'a1': ['id1', 'id2', 'id3', 'id4', 'id1', 'id3', 'id2', 'id2'],
    'b1': [1200.00, 240.20, -298.00, 10000.13, -569.13, 1000.00, 0.00, -32.00],
    'x': ['Meat', 'Dairy', 'Veg', 'Fruit', 'Meat', 'Veg', 'Dairy', 'Fruit'],
    'y': ['Client1', 'Client1', 'Client1', 'Client3', 'Client2', 'Client5', 'Client1', 'Client3']
})

df2 = pd.DataFrame({
    'a2': ['id1', 'id2', 'id3', 'id4'],
    'b2': [1200.0013, -32.0115, -298.0003, 10000.1300],
    'Category': [1, 4, 3, 4]
})

实现方法

方法1:合并后基于容差过滤

先通过ID列合并两个DataFrame,再根据数值列的绝对差筛选符合近似条件的行,最后整理列名:

# 按ID列合并(a1对应a2)
merged_df = pd.merge(df1, df2, left_on='a1', right_on='a2')

# 设置数值匹配容差(根据实际误差调整,示例中误差在0.01内)
tolerance = 0.01

# 筛选b1与b2绝对差小于容差的行
filtered_df = merged_df[abs(merged_df['b1'] - merged_df['b2']) < tolerance]

# 整理目标列,调整列名并重置索引
df3 = filtered_df[['a2', 'b1', 'x', 'y']].rename(columns={'b1': 'b2'}).reset_index(drop=True)

print(df3)

方法2:遍历匹配(适合小数据集)

遍历df2的每一行,在df1中匹配ID一致且数值近似的行,最后合并结果:

matches = []
tolerance = 0.01

for _, df2_row in df2.iterrows():
    # 匹配条件:a1等于a2,且b1与b2的绝对差小于容差
    matched_rows = df1[
        (df1['a1'] == df2_row['a2']) & 
        (abs(df1['b1'] - df2_row['b2']) < tolerance)
    ]
    # 替换列名并整理结构
    matched_rows = matched_rows.assign(a2=df2_row['a2'], b2=matched_rows['b1']).drop(columns=['a1', 'b1'])
    matches.append(matched_rows)

# 合并所有匹配行并重置索引
df3 = pd.concat(matches).reset_index(drop=True)

print(df3)

关键注意事项

  • 容差tolerance需根据实际数据的舍入误差范围调整,比如误差在0.001内则设为0.001
  • 若存在多对一的匹配情况(同一ID+近似数值对应多个df1行),两种方法都会保留所有匹配结果,可按需添加去重逻辑
  • 若需要保留df2的b2原始值而非df1的b1,只需调整列选择(比如方法1中选择merged_df['b2']即可)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 01:37:02