如何在特定级别重新排序多索引数据框列
Posted
技术标签:
【中文标题】如何在特定级别重新排序多索引数据框列【英文标题】: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'])
符合我的预期,但感觉就像我在做额外的工作。有没有更简单的方法来做到这一点?
【问题讨论】:
在这里以最佳方式回答:***.com/questions/40570679/… 【参考方案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】:这是对我有用的最简单的一个:
对于您选择的级别,创建一个包含所需顺序的列的列表;
重新索引您的列并从该列表创建一个 MultiIndex 对象,记住这会返回一个元组;
使用 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
【讨论】:
这并不能回答问题,因为它不适用于已取消堆叠为列的索引级别。以上是关于如何在特定级别重新排序多索引数据框列的主要内容,如果未能解决你的问题,请参考以下文章