如何在特定级别重新排序多索引数据框列

Tim*_*omb 21 python pandas

我有一个多索引DataFrame,其名称附加到列级别.我希望能够轻松地改变列周围的列,以便它们匹配用户指定的顺序.由于这是在管道中,我无法使用此推荐的解决方案并在创建时正确地订购它们.

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

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
Run Code Online (Sandbox Code Playgroud)

我想要列出一个列表,['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  
Run Code Online (Sandbox Code Playgroud)

需要注意的是,我并不总是知道"实验"的级别.我试过了(df上面显示的多索引框架在哪里)

df2 = df.reindex_axis(['IWWGCW', 'IWWGDW', 'BASE'], axis=1, level='Experiment')
Run Code Online (Sandbox Code Playgroud)

但这似乎不起作用 - 它成功完成,但返回的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
Run Code Online (Sandbox Code Playgroud)

reorder_columns(df, 'Experiment', ['IWWGCW', 'IWWGDW', 'BASE'])我的期望在哪里,但感觉我正在做额外的工作.有更简单的方法吗?

rag*_*esz 18

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

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)
Run Code Online (Sandbox Code Playgroud)


Irv*_*Irv 14

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

df.reindex(columns=['IWWGCW', 'IWWGDW', 'BASE'], level='Experiment')
Run Code Online (Sandbox Code Playgroud)

  • 我相信这应该是新接受的答案,因为接受的答案已经过时了。 (2认同)

Ped*_*nna 9

这是对我有用的最简单的方法:

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
Run Code Online (Sandbox Code Playgroud)

在一行中:

df.reindex(columns= df.columns.reindex(['IWWGCW', 'IWWGDW', 'BASE'], 
level = 0)[0])
Run Code Online (Sandbox Code Playgroud)


Wes*_*ney 6

我一无所知。创建了关于它的增强标签:

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

  • 似乎已经通过https://github.com/pydata/pandas/issues/4088解决了 (3认同)
  • 这是语法:`df.reindex(['top','mid','btm'],level ='first')`https://github.com/pandas-dev/pandas/pull/9019 (2认同)
  • `df.reindex(['top', 'mid', 'btm'], level='first')` 不适用于多级列 (2认同)
  • @Tomasz为了对应于OP, `df.reindex_axis(columns=['IWWGCW', 'IWWGDW', 'BASE'], level='Experiment')` 将适用于多级列 (2认同)
  • @BryanP `reindex_axis` 已弃用,但 `df.reindex(columns=['IWWGCW', 'IWWGDW', 'BASE'], level='Experiment')` 应该可以工作(注意:我用 pandas 1.2.0 尝试过此操作) (2认同)