多级索引DataFrame排序未遵循分类索引顺序问题
多级分类索引排序不生效?看这篇解决!
嘿,我懂你遇到的这个坑——明明把多级索引的第二级改成了有序分类,跑df.sort_index()后还是没按One→Two→Three→Four的预期顺序来,单级索引这么操作就好好的,简直离谱对吧?
问题出在哪?
核心原因是:多级索引里,只改levels(层级的可选值集合)没用,还得同步更新codes(每个索引位置对应的层级值编码)。你之前的操作只更新了levels,但原来的codes还是对应旧的字母排序逻辑(比如'Four'的编码比'Three'小),所以排序的时候还是按旧编码来,自然达不到你要的效果。
靠谱的解决方法
给你两种实用方案,按需选:
方案1:从源头设置分类索引
最省心的方式是在创建DataFrame时就把B列设为有序分类,这样后续设置多级索引后排序直接生效:
import pandas as pd # 先把B列定义为有序分类 df = pd.DataFrame( {'A':[1,1,2,2], 'B':pd.Categorical( ['One','Two','Three', 'Four'], categories=['One','Two','Three', 'Four'], ordered=True ), 'X':[1,2,3,4]} ).set_index(['A','B']).sort_index() print(df)
输出直接就是预期的排序:
X A B 1 One 1 Two 2 2 Three 3 Four 4
方案2:修改已有的多级索引
如果已经有现成的DataFrame,不想重新构建,可以提取第二级索引转为分类后重新设置:
# 提取第二级索引,转为指定顺序的有序分类 b_categorical = pd.Categorical( df.index.get_level_values(1), categories=['One','Two','Three', 'Four'], ordered=True ) # 重新设置多级索引 df = df.set_index([df.index.get_level_values(0), b_categorical]) # 现在排序就正常了 df.sort_index()
为啥原来的方法不行?
再给你掰扯清楚:你用df.index.set_levels()的时候,只是把层级的可选值换成了分类,但每个索引位置对应的编码没改——比如原来字母排序下,'Four'的编码是0,'Three'是1。修改levels后编码还是0和1,所以排序时还是会把编码小的'Four'放在'Three'前面。而重新设置索引时,会根据新的分类规则生成正确的编码,这样sort_index就会按照你指定的分类顺序来排啦。
内容的提问来源于stack exchange,提问作者Ymareth
相关产品推荐
相关产品推荐

