pandas merge与merge_ordered合并DataFrame时如何保留原始行顺序
pandas合并DataFrame保留左表原始行顺序
使用pd.merge、pd.merge_ordered合并DataFrame时默认会按合并键对结果排序,导致左表原始行顺序被打乱,可通过以下几种方案解决:
方法1:merge传sort=False参数(pandas 1.1.0及以上版本适用)
高版本pandas的merge方法提供了sort参数,传入sort=False即可禁止自动按合并键排序,直接保留左表原始行顺序,修改代码如下:import pandas as pd cols = ['x1', 'x2'] df = pd.DataFrame([ ['s1', 'a', 'a', 12], ['s2', 'a', 'b', 7], ['s3', 'b', 'a', 14], ['s4', 'b', 'b', 8], ['s5', 'a', 'a', 19], ['s6', 'a', 'b', 16], ['s7', 'b', 'a', 14], ['s8', 'b', 'b', 10] ], columns=['s', 'x1', 'x2', 'y']) y_ = df.groupby(cols).mean() y_.rename(columns={'y': 'y_'}, inplace=True) # 新增sort=False参数 result = pd.merge(df, y_, on=cols, sort=False) print(result)运行后输出和预期结果完全一致。
方法2:添加临时排序列(全版本兼容,适配merge/merge_ordered)
如果使用低版本pandas,或是使用pd.merge_ordered(该方法无内置保留左表顺序的参数),可以先给左表添加一列存储原始行号,合并完成后按该列排序、再删除临时列即可,逻辑稳定无兼容问题:# 给左表添加原始顺序标记 df['_tmp_order'] = range(len(df)) # 执行合并操作,merge/merge_ordered都适用 result = pd.merge(df, y_, on=cols) # 按原始顺序重排后删除临时列 result = result.sort_values('_tmp_order').drop(columns=['_tmp_order']).reset_index(drop=True) print(result)方法3:分组聚合场景用transform替代merge(最优方案)
示例中的场景本质是分组计算统计值后映射回原表,这种场景不需要使用merge,直接用groupby.transform即可实现,从根源上避免顺序错乱,运行效率也更高:import pandas as pd cols = ['x1', 'x2'] df = pd.DataFrame([ ['s1', 'a', 'a', 12], ['s2', 'a', 'b', 7], ['s3', 'b', 'a', 14], ['s4', 'b', 'b', 8], ['s5', 'a', 'a', 19], ['s6', 'a', 'b', 16], ['s7', 'b', 'a', 14], ['s8', 'b', 'b', 10] ], columns=['s', 'x1', 'x2', 'y']) # transform返回的结果和原表行顺序完全对齐 df['y_'] = df.groupby(cols)['y'].transform('mean') print(df)运行后直接得到符合预期顺序的结果,不需要额外排序操作。
内容的提问来源于stack exchange,提问作者Changkun
相关产品推荐
相关产品推荐

