如何将Pandas单索引DataFrame设为类多索引格式并按组排序
问题与实现方案
原始数据与初始操作
先看原始数据的创建及初始索引设置代码:
import pandas as pd df = pd.DataFrame({'X1':[0,5,4,8,9,0,7,6], 'X2':[4,1,3,5,6,2,3,3], 'X3':['A','A','B','B','B','C','C','C']}) df = df.set_index('X3')
执行上述代码后得到普通单索引结构,但需要实现类多索引的显示格式(非真正多索引),即同一X3分组的索引仅在组内第一行显示,后续同组行的索引位置留空,目标显示效果如下:
X1 X2 A 0 4 5 1 B 4 3 8 5 9 6 C 0 2 7 3 6 3
补充排序需求
排序需满足两个条件:
- 以各组
X1的最大值为首要排序依据,最大值大的组整体排在前面 - 同组内的行必须保持在一起,不能拆分分组
实现步骤
1. 按组内X1最大值排序分组
先计算每个X3分组的X1最大值,再以此为依据对分组进行排序,确保同组行不拆分:
# 计算每个X3分组的X1最大值,并按降序排序 group_max = df.groupby('X3')['X1'].max().sort_values(ascending=False) # 按排序后的分组顺序重新排列DataFrame sorted_df = df.loc[group_max.index.repeat(df.groupby('X3').size())]
2. 生成类多索引的显示格式
利用pandas.Styler实现索引的空值显示效果,无需修改实际索引结构:
def format_index(val, first_in_group): # 组内第一行显示索引值,其余行留空 return val if first_in_group else '' # 标记每个组的第一行 sorted_df['is_first'] = sorted_df.groupby(level=0).cumcount() == 0 # 应用索引格式化样式 styled_df = sorted_df.style.format_index(lambda x: format_index(x, sorted_df.loc[x, 'is_first'].iloc[0]), axis=0) # 隐藏辅助判断列is_first styled_df = styled_df.hide(['is_first']) # 查看最终效果 display(styled_df)
完整代码
import pandas as pd # 创建并初始化索引 df = pd.DataFrame({'X1':[0,5,4,8,9,0,7,6], 'X2':[4,1,3,5,6,2,3,3], 'X3':['A','A','B','B','B','C','C','C']}) df = df.set_index('X3') # 按组内X1最大值排序分组 group_max = df.groupby('X3')['X1'].max().sort_values(ascending=False) sorted_df = df.loc[group_max.index.repeat(df.groupby('X3').size())] # 生成类多索引显示格式 def format_index(val, first_in_group): return val if first_in_group else '' sorted_df['is_first'] = sorted_df.groupby(level=0).cumcount() == 0 styled_df = sorted_df.style.format_index(lambda x: format_index(x, sorted_df.loc[x, 'is_first'].iloc[0]), axis=0) styled_df = styled_df.hide(['is_first']) display(styled_df)
效果说明
执行后会得到符合要求的结果:
- 分组按
X1最大值降序排列:先显示B组(最大值9),再显示C组(最大值7),最后是A组(最大值5) - 同一
X3分组的索引仅在组内第一行显示,后续行索引位置留空,呈现类多索引的视觉效果
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

