寻求Pandas两个DataFrame的更高效条件合并实现方法
优化DataFrame条件合并的实现方式
问题背景
我尝试编写最简示例代码实现两个DataFrame的条件合并,基于指定条件匹配对应行,目前需通过双重循环实现。示例代码如下:
import pandas as pd df1 = pd.DataFrame([ ['a', 'Test1', 2995], ['b', 'Test2', 3995], ['c', 'Test3', 5000]], columns=['ID', 'Name', 'Value']) df2 = pd.DataFrame([ ['1', 1, 2], ['2', 3, 4], ['3', 99, 100]], columns=['ID', 'Start', 'Context']) df_test = pd.DataFrame(columns=['ID', 'Name', 'Value','Start']) i = 0 for index, row1 in df1.iterrows(): for index, row2 in df2.iterrows(): if row1['Value'] + 25 > row2['Start'] * 1000 and row1['Value'] < row2['Start'] * 1000: df_test.loc[i] = row1 df_test.loc[i]['Start'] = row2['Start'] i += 1
运行后得到结果:
ID Name Value Start 0 a Test1 2995 3
请问是否存在更优的实现方式?
优化方案
双重循环(尤其是iterrows())的效率极低,当数据量较大时会严重拖慢运行速度。下面推荐两种基于向量化操作的高效实现方式,利用pandas/numpy的底层优化大幅提升性能:
方案1:交叉连接后过滤条件
通过merge(how='cross')生成两个DataFrame的所有行组合,再用布尔索引筛选符合条件的行,最后保留需要的列:
import pandas as pd df1 = pd.DataFrame([ ['a', 'Test1', 2995], ['b', 'Test2', 3995], ['c', 'Test3', 5000]], columns=['ID', 'Name', 'Value']) df2 = pd.DataFrame([ ['1', 1, 2], ['2', 3, 4], ['3', 99, 100]], columns=['ID', 'Start', 'Context']) # 交叉连接,重命名重复列名避免冲突 df_cross = df1.merge(df2, how='cross', suffixes=('_df1', '_df2')) # 应用过滤条件 condition = (df_cross['Value'] + 25 > df_cross['Start'] * 1000) & (df_cross['Value'] < df_cross['Start'] * 1000) # 筛选结果并调整列名 df_result = df_cross.loc[condition, ['ID_df1', 'Name', 'Value', 'Start']].rename(columns={'ID_df1': 'ID'}) print(df_result)
方案2:广播机制匹配条件
利用numpy的广播特性,直接计算所有行的匹配条件,再提取符合条件的行进行合并:
import pandas as pd import numpy as np df1 = pd.DataFrame([ ['a', 'Test1', 2995], ['b', 'Test2', 3995], ['c', 'Test3', 5000]], columns=['ID', 'Name', 'Value']) df2 = pd.DataFrame([ ['1', 1, 2], ['2', 3, 4], ['3', 99, 100]], columns=['ID', 'Start', 'Context']) # 将数据转换为可广播的形状 values = df1['Value'].values[:, np.newaxis] starts = df2['Start'].values * 1000 # 生成条件匹配矩阵 mask = (values + 25 > starts) & (values < starts) # 获取所有匹配的行索引 df1_idx, df2_idx = np.where(mask) # 合并匹配的行数据 df_result = df1.loc[df1_idx].copy() df_result['Start'] = df2.loc[df2_idx, 'Start'].values print(df_result)
方案优势
- 效率提升显著:向量化操作避免了逐行循环的开销,数据量越大,性能优势越明显。
- 代码简洁易维护:逻辑清晰,修改条件或扩展功能更方便。
- 原生支持:完全基于pandas/numpy的原生API,无需额外依赖。
内容的提问来源于stack exchange,提问作者user3732793
相关产品推荐
相关产品推荐

