Pandas MultiIndex按分类顺序自定义排序级别,而不是按字母顺序排序

时间:2015-06-01 13:24:21

标签: python pandas sorting multi-index categorical-data

我是Pandas的新手(0.16.1),并希望在多索引中进行自定义排序,因此我使用了Categoricals。 我的多指数的一部分:

Part  Defect Own
Кузов 504    ИП
Кузов 504    Итого
Кузов 504    ПС
Кузов 505    ПС
Кузов 506    ПС
Кузов 507    ПС
Кузов 530    ИП
Кузов 530    Итого
Кузов 530    ПС

我使用MultiIndex级别创建数据透视表[缺陷,自己]。然后我将“自己的”分类(参见问题的一部分)分类为[ИП,ПС,Итого]。但是当我在“Part”之前添加级别时,“Part”也是基于“缺陷”级别的分类,并且使用

排序索引
pvt.sortlevel(0, inplace=True)

“自己”级别按字母顺序排序:[ИП,Итого,ПС]。如何在multiindex中自定义两个级别?

P上。 S.我使用以下代码将“Own”级别转换为Categorical:创建新列,用它替换索引级别。可以吗?

def makeLevelCategorical(pdf, pname, cats):
    names = pdf.index.names
    namei = names.index(pname)
    pdf["tmp"] = pd.Categorical(pdf.index.get_level_values(pname), categories=cats) #New temp column
    pdf.set_index("tmp", append=True, inplace=True) #Append column to index
    pdf = pdf.reset_index(pname, drop=True) #Remove /pname/ level
    names2 = list(names)
    names2[namei] = "tmp"
    pdf.reorder_levels(names2)  #Put "tmp" level to /pname/'s position
    pdf.index.names = names     #Rename "tmp" level to /pname/
    return pdf

1 个答案:

答案 0 :(得分:2)

可以使用Dataframe.sort_index函数对多索引进行排序。

这是一个小例子:

df = pd.DataFrame(
    {"i1":[1,1,1,1,2,4,4,2,3,3,3,3],
     "i2":[1,3,2,2,1,1,2,2,1,1,3,2],
     "d1":['a','b','c','d','e','f','g','h','i','j','k','l']}
)
df.set_index(['i1', 'i2'], inplace=True)
df.sort_index()

输出:

        d1
i1  i2  
1   1   a
    2   c
    2   d
    3   b
2   1   e
    2   h
3   1   i
    1   j
    2   l
    3   k
4   1   f
    2   g

如果要在列的基础上更改排序顺序,Dataframe.sort_index函数将使用参数ascending=,该参数可以按顺序给出与列对应的[True, False]语句列表。

分类是pandas中的一个新的闪亮dtype,应该使用它,但本身不需要它。

由于评论而编辑:

排序将始终按字母顺序或按相反顺序排序。如果要自定义排序,则需要创建一个新列,该列可以按字母顺序排序,但是可以确定排序的列的结果。使用Series.map执行此操作(如此示例),首先使用元音对数据集进行排序:

mappings = {'a': 0, 'b':1, 'c':1, 'd':1,
            'e':0, 'f':1, 'g':1, 'h':1,
            'i':0, 'j':1, 'k': 1, 'l': 1}
df['sortby'] = df['d1'].map(mappings)
df.sort('sortby')

        d1  sortby
i1  i2      
1   1   a   0
2   1   e   0
3   1   i   0
1   3   b   1
    2   c   1
    2   d   1
4   1   f   1
    2   g   1
2   2   h   1
3   1   j   1
    3   k   1
    2   l   1

如果你之后不想要sortby列,你可以删除它,如下所示:

del df['sortby']