如何按指定规则自动排序含Subtotal行的DataFrame?
实现带Subtotal行的DataFrame自动排序方案
问题描述
需要对大规模DataFrame进行自动化排序,使多处Subtotal行处于对应分组的正确位置(即同分组非汇总行之后,上层汇总行在对应子分组全部完成之后)。
原始未排序DataFrame
import pandas as pd df = pd.DataFrame( {'Comp':['Active','Active','Active','Active','BRAKE','Active','Active','Active','BRAKE','Active','Active','Active','Active'], 'Source':['Env-IRP','Env-IRP','Env-IRP','Env-MM','BRAKE-IRP','Env-MM','Env-IRP','Env-MM','BRAKE-IRP','Env-IRP','Env-IRP','Env-MM','Env-MM'], 'ActCat':['Inv','Inv','RA','Inv','Inv','RA','','','','Inv','RA','Inv','RA'], 'Act':['foo','eggs','buzz','buzz','foo','eggs','Subtotal','Subtotal','Subtotal','Subtotal','Subtotal','Subtotal','Subtotal'], 'OG20':[1,2,3,4,5,6,6,10,5,3,3,4,6], 'OG21':[1,2,3,4,5,6,6,10,5,3,3,4,6],'OG22':[1,2,3,4,5,6,6,10,5,3,3,4,6]})
已尝试的代码
df['sort_helper'] = df['Act'].apply(lambda x: 1 if x == "Subtotal" else 0) df.sort_values(by=['Comp','Source','ActCat','sort_helper','Act'], inplace=True)
期望输出
df = pd.DataFrame( {'Comp':['Active','Active','Active','Active','Active','Active','Active','Active','Active','Active','Active','Active','BRAKE','BRAKE','BRAKE','BRAKE'], 'Source':['Env-IRP','Env-IRP','Env-IRP','Env-IRP','Env-IRP','Env-IRP','Env-MM','Env-MM','Env-MM','Env-MM','Env-MM','','BRAKE-IRP','BRAKE-IRP','BRAKE-IRP',''], 'ActCat':['Inv','Inv','Inv','RA','RA','','Inv','Inv','RA','RA','','','Inv','Inv','',''], 'Act':['foo','eggs','Subtotal','buzz','Subtotal','Subtotal','buzz','Subtotal','eggs','Subtotal','Subtotal','Subtotal','foo','Subtotal','Subtotal','Subtotal'], 'OG20':[1,2,3,3,3,6,4,4,6,6,10,16,6,6,6,6], 'OG21':[1,2,3,3,3,6,4,4,6,6,10,16,6,6,6,6],'OG22':[1,2,3,3,3,6,4,4,6,6,10,16,6,6,6,6]})
解决方案
核心思路是通过排序辅助键确保Subtotal始终处于同分组最后,同时利用Pandas空值排序特性处理上层汇总行。
基础实现方案
# 生成排序辅助键:Subtotal标记为1,其余为0,确保汇总行在同分组最后 df['sort_key'] = df['Act'].map(lambda x: 1 if x == 'Subtotal' else 0) # 按层级分组维度排序,空值默认排在最后,匹配上层汇总逻辑 df_sorted = df.sort_values( by=['Comp', 'Source', 'ActCat', 'sort_key', 'Act'], na_position='last' ).drop('sort_key', axis=1) # 输出结果 print(df_sorted)
保持非汇总行原始顺序的变种
如果需要保留同分组内非Subtotal行的原始顺序,可通过groupby生成组内序号替代Act作为排序键:
# 生成组内序号,保留原始顺序 df['group_seq'] = df.groupby(['Comp', 'Source', 'ActCat'])['Act'].cumcount() df['sort_key'] = df['Act'].map(lambda x: 1 if x == 'Subtotal' else 0) # 按层级+辅助键+组内序号排序 df_sorted = df.sort_values( by=['Comp', 'Source', 'ActCat', 'sort_key', 'group_seq'], na_position='last' ).drop(['sort_key', 'group_seq'], axis=1)
方案说明
- sort_key的作用:让同分组内所有非汇总行优先排序,Subtotal行紧随其后
- 层级排序维度:
Comp→Source→ActCat严格对应分组层级,确保同类别行聚集 - 空值处理:
na_position='last'让空值的分组行(如空ActCat、空Source)排在对应子分组之后,正好匹配上层汇总的Subtotal逻辑
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

