如何基于列等值匹配与数值差值条件合并Pandas DataFrame
当然可以实现这种带额外数值条件的连接!你提到的先合并再过滤是最直观的思路,不过我们还有更简洁的写法,甚至能针对大数据场景做优化,下面给你几种实用方案:
方案1:先合并后过滤(最易理解)
先基于col1做等值内连接,为了区分两个表的col2,我们给它们加上后缀,之后再筛选col2绝对差值小于10的行:
import pandas as pd # 初始化你的DataFrame d = {'col1': ['A', 'B'], 'col2': [30, 40]} df = pd.DataFrame(data=d) d1 = {'col1': ['A', 'B'], 'col2': [35, 400]} df1 = pd.DataFrame(data=d1) # 合并两个表,重命名重复的col2列 merged_df = df.merge(df1, on='col1', suffixes=('_df', '_df1')) # 应用差值过滤条件 final_result = merged_df[abs(merged_df['col2_df'] - merged_df['col2_df1']) < 10] print(final_result)
运行后只会保留col1为A的行,因为35和30的差值是5,满足小于10的条件;而B对应的40和400差值太大,会被过滤掉。
方案2:用
query简化代码 如果想让代码更紧凑,可以把合并和过滤步骤合并成一行,用query方法写过滤条件,可读性更强:
final_result = df.merge(df1, on='col1', suffixes=('_df', '_df1')).query('abs(col2_df - col2_df1) < 10')
这个方案和方案1的效果完全一致,但代码更简洁,适合快速实现需求。
方案3:提前分组过滤(大数据场景优化)
如果你的数据集非常大,先合并再过滤会生成一个庞大的中间表,浪费内存。这时候可以提前按col1分组,只保留符合差值条件的行:
from collections import defaultdict # 把df1按col1分组,存储对应的col2值 col1_col2_map = defaultdict(list) for _, row in df1.iterrows(): col1_col2_map[row['col1']].append(row['col2']) # 遍历df,筛选符合条件的配对行 result_rows = [] for _, row in df.iterrows(): current_col1 = row['col1'] current_col2 = row['col2'] # 检查同col1下的所有col2值,筛选差值符合条件的 for val in col1_col2_map.get(current_col1, []): if abs(current_col2 - val) < 10: result_rows.append({ 'col1': current_col1, 'col2_df': current_col2, 'col2_df1': val }) final_result = pd.DataFrame(result_rows)
这种方法避免了生成不必要的中间数据,在数据量较大时能显著提升性能。
补充说明:Pandas的merge方法本身只支持等值连接,没法直接在merge参数里指定数值差值类的条件,所以先合并后过滤是最常用的常规方案;如果追求代码简洁,query是很好的选择;大数据场景下,提前分组过滤会更高效。
内容的提问来源于stack exchange,提问作者ZakS
相关产品推荐
相关产品推荐

