【问题标题】:How can I reorder multi-indexed dataframe columns at a specific level如何在特定级别重新排序多索引数据框列
【发布时间】:2012-06-27 00:28:39
【问题描述】:

我有一个多索引DataFrame,其名称附加到列级别。我希望能够轻松地打乱列,使它们与用户指定的顺序相匹配。由于这是在管道中,我无法使用 this recommended solution 并在创建时正确排序它们。

我有一个看起来(有点)像的数据表

Experiment           BASE           IWWGCW         IWWGDW
Lead Time                24     48      24     48      24     48
2010-11-27 12:00:00   0.997  0.991   0.998  0.990   0.998  0.990
2010-11-28 12:00:00   0.998  0.987   0.997  0.990   0.997  0.990
2010-11-29 12:00:00   0.997  0.992   0.997  0.992   0.997  0.992
2010-11-30 12:00:00   0.997  0.987   0.997  0.987   0.997  0.987
2010-12-01 12:00:00   0.996  0.986   0.996  0.986   0.996  0.986

我想获取像['IWWGCW', 'IWWGDW', 'BASE'] 这样的列表并将其重新排序为:

Experiment           IWWGCW         IWWGDW         BASE           
Lead Time                24     48      24     48      24     48  
2010-11-27 12:00:00   0.998  0.990   0.998  0.990   0.997  0.991  
2010-11-28 12:00:00   0.997  0.990   0.997  0.990   0.998  0.987  
2010-11-29 12:00:00   0.997  0.992   0.997  0.992   0.997  0.992  
2010-11-30 12:00:00   0.997  0.987   0.997  0.987   0.997  0.987  
2010-12-01 12:00:00   0.996  0.986   0.996  0.986   0.996  0.986  

需要注意的是,我并不总是知道“实验”会达到什么级别。我试过了(df 是上面显示的多索引框架)

df2 = df.reindex_axis(['IWWGCW', 'IWWGDW', 'BASE'], axis=1, level='Experiment')

但这似乎不起作用 - 它成功完成,但返回的 DataFrame 的列顺序未更改。

我的解决方法是使用如下功能:

def reorder_columns(frame, column_name, new_order):
    """Shuffle the specified columns of the frame to match new_order."""

    index_level  = frame.columns.names.index(column_name)
    new_position = lambda t: new_order.index(t[index_level])
    new_index    = sorted(frame.columns, key=new_position)
    new_frame    = frame.reindex_axis(new_index, axis=1)
    return new_frame

reorder_columns(df, 'Experiment', ['IWWGCW', 'IWWGDW', 'BASE']) 符合我的预期,但感觉就像我在做额外的工作。有没有更简单的方法来做到这一点?

【问题讨论】:

标签: python pandas


【解决方案1】:

有一个非常简单的方法:只需在原始数据框的基础上创建一个新的数据框,并使用正确的多索引列顺序:

multi_tuples = [('IWWGCW',24), ('IWWGCW',48), ('IWWGDW',24), ('IWWGDW',48)
    , ('BASE',24), ('BASE',48)]

multi_cols = pd.MultiIndex.from_tuples(multi_tuples, names=['Experiment', 'Lead Time'])

df_ordered_multi_cols = pd.DataFrame(df_ori, columns=multi_cols)

【讨论】:

    【解决方案2】:

    这是对我有用的最简单的一个:

    1. 对于您选择的级别,创建一个包含所需顺序的列的列表;

    2. 重新索引您的列并从该列表创建一个 MultiIndex 对象,记住这会返回一个元组;

    3. 使用 MultiIndex 对象重新排序您的 DataFrame。

    cols = ['IWWGCW', 'IWWGDW', 'BASE']
    new_cols = df.columns.reindex(cols, level=0)
    df.reindex(columns=new_cols[0]) #new_cols is a single item tuple
    

    一行:

    df.reindex(columns=df.columns.reindex(['IWWGCW', 'IWWGDW', 'BASE'], level=0)[0])
    

    【讨论】:

      【解决方案3】:

      我什么都不知道。创建了一张关于它的增强票:

      http://github.com/pydata/pandas/issues/1864

      【讨论】:

      • 这是语法:df.reindex(['top', 'mid', 'btm'], level='first')github.com/pandas-dev/pandas/pull/9019
      • df.reindex(['top', 'mid', 'btm'], level='first') 不适用于多级列
      • 对我有用的(次优)解决方法:df.T.reindex(['top', 'mid', 'btm'], level='first').T
      • @Tomasz 为了对应 OP,df.reindex_axis(columns=['IWWGCW', 'IWWGDW', 'BASE'], level='Experiment') 将适用于多级列
      • @BryanP reindex_axis 已弃用,但 df.reindex(columns=['IWWGCW', 'IWWGDW', 'BASE'], level='Experiment') 应该可以工作(注意:我在 pandas 1.2.0 上试过)
      【解决方案4】:

      我上面评论中的解决方案,使用 pandas 1.3.2:

      df.reindex(columns=['IWWGCW', 'IWWGDW', 'BASE'], level='Experiment')
      

      【讨论】:

      • 我相信这应该是新接受的答案,因为接受的答案已经过时了。
      【解决方案5】:

      comment by andrew_reece 应该是公认的答案。只需使用reindex()

      github issue复制粘贴:

      >>> df
                           vals
      first second third       
      mid   3rd    992     1.96
                   562    12.06
            1st    73     -6.46
                   818   -15.75
                   658     5.90
      btm   2nd    915     9.75
                   474    -1.47
                   905    -6.03
            1st    717     8.01
                   909   -21.12
            3rd    616    11.91
                   675     1.06
                   579    -4.01
      top   1st    241     1.79
                   363     1.71
            3rd    677    13.38
                   238   -16.77
                   407    17.19
            2nd    728   -21.55
                   36      8.09
      >>> df.reindex(['top', 'mid', 'btm'], level='first')
                           vals
      first second third       
      top   1st    241     1.79
                   363     1.71
            3rd    677    13.38
                   238   -16.77
                   407    17.19
            2nd    728   -21.55
                   36      8.09
      mid   3rd    992     1.96
                   562    12.06
            1st    73     -6.46
                   818   -15.75
                   658     5.90
      btm   2nd    915     9.75
                   474    -1.47
                   905    -6.03
            1st    717     8.01
                   909   -21.12
            3rd    616    11.91
                   675     1.06
                   579    -4.01
      >>> df.reindex(['1st', '2nd', '3rd'], level='second')
                           vals
      first second third       
      mid   1st    73     -6.46
                   818   -15.75
                   658     5.90
            3rd    992     1.96
                   562    12.06
      btm   1st    717     8.01
                   909   -21.12
            2nd    915     9.75
                   474    -1.47
                   905    -6.03
            3rd    616    11.91
                   675     1.06
                   579    -4.01
      top   1st    241     1.79
                   363     1.71
            2nd    728   -21.55
                   36      8.09
            3rd    677    13.38
                   238   -16.77
                   407    17.19
      >>> df.reindex(['top', 'btm'], level='first').reindex(['1st', '2nd'], level='second')
                           vals
      first second third       
      top   1st    241     1.79
                   363     1.71
            2nd    728   -21.55
                   36      8.09
      btm   1st    717     8.01
                   909   -21.12
            2nd    915     9.75
                   474    -1.47
                   905    -6.03
      

      【讨论】:

      • 这并不能回答问题,因为它不适用于已取消堆叠为列的索引级别。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      • 2018-08-24
      • 2019-02-05
      • 2013-12-04
      • 2018-06-19
      • 2019-12-20
      相关资源
      最近更新 更多