如何实现DataFrame每行与另一DataFrame带容差对比并获取匹配索引
高效实现DataFrame带容差的行匹配方案
问题分析
你之前的尝试存在两个核心问题:
df.compare并非用于自定义规则的跨DataFrame行匹配,它的设计目标是对比同结构、同索引DataFrame的元素差异,因此报错属于预期情况。- Python双重循环的时间复杂度为O(M*K)(M为df1行数,K为df2行数),当df1达到数万行时,效率会急剧下降,完全无法适配大规模数据场景。
高效向量化实现方案
利用numpy的广播机制实现批量计算,避免Python层面的循环,充分利用底层C优化的计算能力,效率比循环提升几个数量级。
核心逻辑
- 对df1和df2的数组进行维度扩展,通过广播实现所有行对的元素级计算
- 按规则判断每个元素是否满足
x > y或|x - y| ≤ 2.5 - 对每个行对检查所有列是否都满足规则
- 提取满足条件的df2索引,整理为结果DataFrame
代码实现
import pandas as pd import numpy as np def match_dfs(df1, df2, abs_tol=2.5): # 转换为numpy数组,获取原始形状(M,N)和(K,N) arr1 = df1.to_numpy() arr2 = df2.to_numpy() # 广播扩展维度:将arr1转为(M,1,N),arr2转为(1,K,N),实现所有行对的元素级计算 condition = (arr1[:, np.newaxis, :] > arr2[np.newaxis, :, :]) | \ (np.abs(arr1[:, np.newaxis, :] - arr2[np.newaxis, :, :]) <= abs_tol) # 对每个行对,检查所有列是否都满足规则(沿列维度取all) all_cols_valid = condition.all(axis=2) # 结果形状为(M,K)的布尔矩阵 # 整理每个df1行对应的匹配df2索引列表 matched_indices_list = [] for row_mask in all_cols_valid: matched_indices = df2.index[row_mask].tolist() matched_indices_list.append(matched_indices) # 返回与df1索引对齐的结果DataFrame return pd.DataFrame({'matched_df2_indices': matched_indices_list}, index=df1.index)
可选:展开为匹配对格式
如果需要将结果展开为每行一个(df1索引, df2索引)的匹配对,可以使用以下版本:
def match_dfs_flattened(df1, df2, abs_tol=2.5): arr1 = df1.to_numpy() arr2 = df2.to_numpy() condition = (arr1[:, np.newaxis, :] > arr2[np.newaxis, :, :]) | \ (np.abs(arr1[:, np.newaxis, :] - arr2[np.newaxis, :, :]) <= abs_tol) all_cols_valid = condition.all(axis=2) # 获取所有满足条件的行对索引 df1_idx_pos, df2_idx_pos = np.where(all_cols_valid) result = pd.DataFrame({ 'df1_index': df1.index[df1_idx_pos], 'df2_index': df2.index[df2_idx_pos] }) return result
测试示例
# 构造测试数据 df1 = pd.DataFrame( {'col1': [10, 5, 8], 'col2': [20, 15, 18]}, index=['row_a', 'row_b', 'row_c'] ) df2 = pd.DataFrame( {'col1': [7, 13, 5], 'col2': [17, 23, 14]}, index=['match_x', 'match_y', 'match_z'] ) # 运行匹配 result = match_dfs(df1, df2) print(result)
输出结果:
matched_df2_indices row_a [match_x, match_z] row_b [match_x, match_z] row_c [match_x, match_z]
内容的提问来源于stack exchange,提问作者Lev Zhitnik
相关产品推荐
相关产品推荐

