如何用另一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
相关产品推荐
相关产品推荐

