使用多重索引在 pandas DataFrame 中改变索引的顺序

4
我将尝试找到一种简单的方法来更改pandas DataFrame多重索引中值的顺序。为了说明我的意思,假设我们有一个DataFrame,其多重索引定义如下:
index = pd.MultiIndex(levels=[[u'C', u'D', u'M'], [u'C', u'D', u'M']],
           labels=[[0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 1, 2, 0, 1, 2, 0, 1, 2]],
           names=[u'level0', u'level1'])

df = pd.DataFrame(np.random.randint(10,size=(9,3)),index=index,columns=['C','M','D'])

我们有一个DataFrame df,如下所示:

enter image description here

我想做的是将Multiindex的顺序从“C D M”(按字母顺序排序)更改为“C M D”,在level0和level1中都要更改。我尝试使用pd.reindex,但没有找到实现此目标的简单方法。
以下是Jezrael给出的答案,可以显示正确的结果:
L = list('CMD')
mux = pd.MultiIndex.from_product([L, L], names=df.index.names)
df = df.reindex(mux)
print (df)

然而,我需要的是索引级别按照"C M D"的顺序。如果我们检查df.index,我们会得到以下结果:

MultiIndex(levels=[[u'C', u'D', u'M'], [u'C', u'D', u'M']],
           labels=[[0, 0, 0, 2, 2, 2, 1, 1, 1], [0, 2, 1, 0, 2, 1, 0, 2, 1]],
           names=[u'level0', u'level1'])

请注意,“levels”仍按“C D M”的顺序排列。我想要的是,当我使用df.unstack()时,我仍然可以按照“C M D”的顺序获取索引。很抱歉没有表述清楚。
1个回答

3

使用 reindex 方法,通过新的 MultiIndex.from_product 创建多重索引:

np.random.seed(2018)
index = pd.MultiIndex(levels=[[u'C', u'D', u'M'], [u'C', u'D', u'M']],
           labels=[[0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 1, 2, 0, 1, 2, 0, 1, 2]],
           names=[u'level0', u'level1'])

df = pd.DataFrame(np.random.randint(10,size=(9,3)),
                  index=index,columns=['C','M','D'])
print (df)
               C  M  D
level0 level1         
C      C       6  2  9
       D       5  4  6
       M       9  9  7
D      C       9  6  6
       D       1  0  6
       M       5  6  7
M      C       0  7  8
       D       7  9  4
       M       8  1  2

L = list('CMD')
mux = pd.MultiIndex.from_product([L, L], names=df.index.names)
df = df.reindex(mux)
print (df)
               C  M  D
level0 level1         
C      C       6  2  9
       M       9  9  7
       D       5  4  6
M      C       0  7  8
       M       8  1  2
       D       7  9  4
D      C       9  6  6
       M       5  6  7
       D       1  0  6

编辑:

如果需要设置排序,请创建 有序的 CategoricalIndex,然后简单地使用 sort_index 方法进行排序:

L = pd.CategoricalIndex(list('CDM'), ordered=True, categories=list('CMD'))
df.index = pd.MultiIndex.from_product([L, L], names=df.index.names)
df = df.sort_index()
print (df)
               C  M  D
level0 level1         
C      C       6  2  9
       M       9  9  7
       D       5  4  6
M      C       0  7  8
       M       8  1  2
       D       7  9  4
D      C       9  6  6
       M       5  6  7
       D       1  0  6

请查看unstack以获取新的排序方式:

print (df.unstack())
        C        M        D      
level1  C  M  D  C  M  D  C  M  D
level0                           
C       6  9  5  2  9  4  9  7  6
M       0  8  7  7  1  9  8  2  4
D       9  5  1  6  6  0  6  7  6

感谢您的快速回复,非常感激。我还有另一个问题,这种方法无法解决。我已经编辑了问题。很抱歉没有表达清楚我的目标。 - user3821012

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接