Pandas 如何实现类Excel风格多级索引透视表按分组总计数逐级排序
实现Pandas透视表类Excel逐级分组排序的方法
实现核心思路
要实现和Excel透视表一致的逐级分组排序,不能用Pandas默认的整行值全局排序,需满足两个核心约束:
- 每一级索引的排序范围严格限制在它的父分组内,不会跨组调整层级归属顺序
- 排序依据是每个索引节点下所有子项的
Totals列汇总值,而非单个行的数值
具体执行步骤:
- 先把透视表中位于最后一行的全局总计行单独剥离出来,避免它参与主体数据的排序流程,后续拼接时固定放在结果最底部
- 按照索引层级从高到低(第一级Name→第二级A→第三级B),分别计算每一行所属分组的
Totals列汇总值,作为对应层级的排序依据 - 用这三个层级的排序值对主体数据做多级降序排序
- 把之前剥离的全局总计行拼回排序后的表尾部,得到最终结果
可直接运行的完整实现代码
import pandas as pd import numpy as np # 复现原始示例数据 df = pd.DataFrame({ "A": ["foo", "foo", "foo", "foo", "foo", "bar", "bar", "bar", "bar", "zz", "zz"], "B": ["one", "one", "one", "two", "two", "one", "one", "two", "two", "xy", "zz"], "Name": ["Peter", "Amy", "Brian", "Amy", "Amy", "Peter", "Brian", "Peter", "Brian", "Brian", "Brian"], "Year": [2019, 2019, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2019, 2020], "Values": [20, 4, 20, 5, 6, 6, 8, 9, 9, 10, 5] }) # 生成初始透视表 df_pivot = pd.pivot_table( df, values='Values', index=['Name','A', 'B'], columns=['Year'], aggfunc=np.sum, fill_value=0, margins=True, margins_name="Totals" ) # 1. 剥离全局索引级的总计行,不参与主体排序 total_row_mask = df_pivot.index.get_level_values(0) == 'Totals' df_body = df_pivot.loc[~total_row_mask].copy() df_total_row = df_pivot.loc[total_row_mask].copy() # 2. 逐级构造组内排序键 # 一级索引Name:按全Name分组的Totals总和降序 sort_key_name = df_body.groupby(level='Name')['Totals'].transform('sum') # 二级索引A:在对应Name组内,按A分组的Totals总和降序 sort_key_a = df_body.groupby(level=['Name', 'A'])['Totals'].transform('sum') # 三级索引B:在对应(Name,A)父组内,按B分组的Totals总和降序 sort_key_b = df_body.groupby(level=['Name', 'A', 'B'])['Totals'].transform('sum') # 3. 基于多级排序键完成主体数据排序 df_sorted_body = df_body.sort_values( by=[sort_key_name, sort_key_a, sort_key_b], ascending=[False, False, False] ) # 4. 拼回全局总计行,得到最终结果 final_sorted_pivot = pd.concat([df_sorted_body, df_total_row])
排序结果验证
运行上述代码后输出的结果完全匹配需求的最终透视表:
Year 2019 2020 Totals Name A B Brian foo one 20 0 20 bar two 0 9 9 one 0 8 8 zz xy 10 0 10 zz 0 5 5 Peter foo one 20 0 20 bar two 0 9 9 one 6 0 6 Amy foo two 11 0 11 one 4 0 4 Totals 71 31 102
适配说明
如果后续增加更多层级的索引,只需按照相同逻辑,为新增层级生成对应分组深度的Totals汇总值作为排序键,即可复用这套逻辑,不需要修改核心排序流程。
内容的提问来源于stack exchange,提问作者Paweł Poprawski
相关产品推荐
相关产品推荐

