Pandas首列分组内次列排序且首列顺序无关的最高效实现方法
3亿行两列的场景下,df.sort_values(by=["ID", "Date"])已经是pandas原生实现中的最优解,你测试出的性能差距已经能直接说明两种方案的效率差异,具体原因和可优化的方向如下:
为什么groupby方案性能远低于双列排序
- groupby操作首先要对ID列做哈希分桶,产生基础的分组开销,之后每个分组单独调用
sort_values会产生大量Python层函数调用、中间对象复制的额外开销,ID基数越高这个开销越夸张,完全比不上pandas底层用C实现的整体多路归并排序效率。
双列排序的可优化点,能进一步降低耗时
如果要进一步压缩8分钟的全量处理时间,可以先做数据类型优化,减小排序时的内存开销和对比开销:
- 把ID列转成
category类型:如果ID是字符串类型,转分类类型后底层会用整数编码存储,排序时只需要对比整数,比字符串对比快3~5倍,内存占用也会下降50%以上 - 确保Date列是
datetime64类型:不要把日期存为字符串,日期类型底层也是整数时间戳存储,排序对比效率远高于字符串
代码示例:
# 先做类型转换 df["ID"] = df["ID"].astype("category") df["Date"] = pd.to_datetime(df["Date"]) # 再执行排序,ignore_index可以按需开启 df_sorted = df.sort_values(by=["ID", "Date"], ignore_index=True)
调整完类型后,全量排序耗时通常可以降低30%以上。
如果你的内存不足以放下全量3亿行数据,也可以采用哈希分块排序的思路:按ID的哈希值把相同ID的行分到同一个小文件块,每个块单独按ID+Date排序后直接拼接即可,不需要再做全局归并,内存占用会低很多,整体性能和全量排序接近。
最终结论
目前pandas没有原生提供「仅按ID聚合、同ID块内按Date排序、ID块之间顺序任意」的专用接口,自己在Python层实现的自定义逻辑性能都远低于原生优化过的双列排序,你当前使用的双列排序就是该场景下的最优方案。
内容的提问来源于stack exchange,提问作者Jon Hearn
相关产品推荐
相关产品推荐

