【问题标题】:Sort dataframe multiindex level and by column对数据框多索引级别和按列进行排序
【发布时间】:2018-10-09 05:10:10
【问题描述】:

更新:pandas 0.23.0 版解决了这个问题

Sorting by a combination of columns and index levels


我一直在努力解决这个问题,我怀疑有更好的方法。如何按索引级别名称“idx_0”、级别=0 和列“value_1”降序对以下数据帧进行排序,以使“MyName”列读取垂直“SCOTTBOSTON”。

import pandas as pd
import numpy as np
df = pd.DataFrame({'idx_0':[2]*6+[1]*5,
                   'idx_1':[6,4,2,10,18,5,11,1,7,9,3],
                   'value_1':np.arange(11,0,-1),
                   'MyName':list('BOSTONSCOTT')})

df = df.set_index(['idx_0','idx_1'])
df

输出:

            MyName  value_1
idx_0 idx_1                
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1

使用例外的输出:

df.sort_values(['value_1'], ascending=False)\
  .reindex(sorted(df.index.get_level_values(0).unique()), level=0)

我怀疑有一种更简单的方法,无需重置索引

            MyName  value_1
idx_0 idx_1                
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6

失败#1:

df.sort_values('value_1', ascending=False).sort_index(level=0)

首先按值排序,然后排序索引 level=0,但 level=1 也会排序。

            MyName  value_1
idx_0 idx_1                
1     1          C        4
      3          T        1
      7          O        3
      9          T        2
      11         S        5
2     2          S        9
      4          O       10
      5          N        6
      6          B       11
      10         T        8
      18         O        7

失败 #2

df.sort_index(level=0).sort_values('value_1', ascending=False)

按索引级别 = 0 排序,然后按值排序,但索引 = 0 再次变得混乱。

            MyName  value_1
idx_0 idx_1                
2     6          B       11
      4          O       10
      2          S        9
      10         T        8
      18         O        7
      5          N        6
1     11         S        5
      1          C        4
      7          O        3
      9          T        2
      3          T        1

【问题讨论】:

  • 我找不到任何优雅的解决方案。这是一种选择:df.reset_index(level=0).sort_values(['idx_0','value_1'], ascending=[1,0]).set_index('idx_0', append=True).swaplevel(),但您的版本看起来更好......

标签: python pandas dataframe multi-index


【解决方案1】:

使用 pandas 版本 0.23.0 更新

Sorting by a combination of columns and index levels

df.sort_values(by=['idx_0','value_1'], ascending=[True,False])

输出:

             value_1 MyName
idx_0 idx_1                
1     11           5      S
      1            4      C
      7            3      O
      9            2      T
      3            1      T
2     6           11      B
      4           10      O
      2            9      S
      10           8      T
      18           7      O
      5            6      N

有趣的是,@jxc 指出了一个我认为应该可行的解决方案,并且几乎正是我的第一次失败。

df.sort_values('value_1', ascending=False)\
  .sort_index(level=0, ascending=[True])

正是传递的ascending 作为列表使上述语句作为例外工作。我认为在熊猫中传递一个标量值和一个列表应该是一样的。但是,在这种情况下,它似乎工作不一样。

我会提交一份错误报告。

【讨论】:

    【解决方案2】:

    以下是满足您需求的一些潜在解决方案:

    方法一:

     (df.sort_values('value_1', ascending=False)
        .sort_index(level=[0], ascending=[True]))
    

    方法二:

     (df.set_index('value_1', append=True)
        .sort_index(level=[0,2], ascending=[True,False])
        .reset_index('value_1'))
    

    在 pandas 0.22.0、Python 3.6.4 上测试

    【讨论】:

    • 您的方法一之所以有效,是因为 sort_index 中的 level 参数的列表而不是标量?
    • 如果你查看源代码,set_index() 有一个参数 sort_remaining=True。这就是为什么当您在第 0 级排序时,其他级别仍会参与其中。当你提供一个列表时,它会筛选出其他级别作为剩余级别。要获得确切的答案,您必须深入研究他们的源代码。
    • 啊...剩下的可能是我要找的东西。
    【解决方案3】:

    这是我丑陋的选择:

    In [139]: (df.assign(x=df.index.get_level_values(0) * \
                           10**np.ceil(np.log10(df.value_1.max()))-df.value_1)
                 .sort_values('x')
                 .drop('x',1))
    Out[139]:
                MyName  value_1
    idx_0 idx_1
    1     11         S        5
          1          C        4
          7          O        3
          9          T        2
          3          T        1
    2     6          B       11
          4          O       10
          2          S        9
          10         T        8
          18         O        7
          5          N        6
    

    一些解释:

    In [140]: np.ceil(np.log10(df.value_1.max()))
    Out[140]: 2.0
    
    In [141]: df.assign(x=df.index.get_level_values(0)*10**np.ceil(np.log10(df.value_1.max()))-df.value_1)
    Out[141]:
                MyName  value_1      x
    idx_0 idx_1
    2     6          B       11  189.0
          4          O       10  190.0
          2          S        9  191.0
          10         T        8  192.0
          18         O        7  193.0
          5          N        6  194.0
    1     11         S        5   95.0
          1          C        4   96.0
          7          O        3   97.0
          9          T        2   98.0
          3          T        1   99.0
    

    另一种选择是添加idx_0 按它和value_1 排序并删除该附加列:

    In [142]: (df.assign(x=df.index.get_level_values(0)).sort_values(['x', 'value_1'], ascending=[1,0])
                 .drop('x',1))
    Out[142]:
                MyName  value_1
    idx_0 idx_1
    1     11         S        5
          1          C        4
          7          O        3
          9          T        2
          3          T        1
    2     6          B       11
          4          O       10
          2          S        9
          10         T        8
          18         O        7
          5          N        6
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 2018-08-27
      • 2019-06-29
      • 2017-12-26
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      相关资源
      最近更新 更多