Pandas查找B列中小于A列对应值的最接近最大值
解决方案
你要的逻辑可以直接用pandas.merge_asof实现,不需要逐行遍历,性能适配大体量数据集,核心思路是:将B列的唯一值提取、排序后构造独立的匹配右表,通过有序近似匹配直接找到每个A值对应的、严格小于它的最大B值,最后还原原表的行顺序即可。
可直接运行的代码
import pandas as pd # 示例测试数据 df = pd.DataFrame({'a' : [1, 5, 7, 2, 3, 4], 'b' : [5, 2, 7, 5, 1, 9]}) # 1. 构造匹配右表:取B列所有唯一值,排序后作为匹配基准 right_table = df[['b']].drop_duplicates().sort_values('b').reset_index(drop=True) # 2. 构造左表:保留原行索引,按A列排序满足merge_asof的有序要求 left_table = df[['a']].reset_index(names='origin_idx').sort_values('a') # 3. 执行asof匹配:找严格小于A值的最大B值 match_result = pd.merge_asof( left_table, right_table, left_on='a', right_on='b', direction='backward', allow_exact_matches=False # 关闭等值匹配,保证结果严格小于A列值 ) # 4. 按原索引还原行顺序,将结果赋值到新列c df['c'] = match_result.set_index('origin_idx')['b']
结果验证
执行后打印df,输出完全符合预期:
a b c 0 1 5 NaN 1 5 2 2.0 2 7 7 5.0 3 2 5 1.0 4 3 1 2.0 5 4 9 2.0
低版本兼容说明
如果你的pandas版本低于1.0,不支持allow_exact_matches参数,可以在匹配后手动过滤不符合要求的等值结果:
match_result = pd.merge_asof( left_table, right_table, left_on='a', right_on='b', direction='backward' ) # 手动剔除大于等于A值的匹配项 match_result.loc[match_result['b'] >= match_result['a'], 'b'] = pd.NA df['c'] = match_result.set_index('origin_idx')['b']
性能说明
整个实现的时间复杂度为O(n log n),主要来自排序步骤,merge_asof本身为线性遍历逻辑,相比逐行apply、循环查找的*O(n²)*复杂度,在十万、百万级数据量下性能差距可达上百倍,适配大体量DataFrame场景。
内容的提问来源于stack exchange,提问作者Joey
相关产品推荐
相关产品推荐

