基于我在另一个问题上找到的具有多级列的示例DataFrame:
arrays = [[1, 2]*3, ['A', 'B', 'C']*2]
columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar'])
df = pd.DataFrame(np.random.randn(2,6),
columns=columns,
index= pd.date_range('20000103',periods=2))
print(df)
foo 1 2 1 2 1 2
bar A B C A B C
2000-01-03 2.040867 -1.727071 0.126223 2.101799 1.811349 -0.003293
2000-01-04 -2.644979 0.156852 -1.034756 0.609625 -0.213968 -0.293759
我需要重新排序列标签,而不是遵循这种模式,根据需要重新对齐数据:
bar A A B B C C
foo 1 2 1 2 1 2
2000-01-03 2.040867 2.101799 1.811349 -1.727071 0.126223 -0.003293
2000-01-04 -2.644979 0.609625 -0.213968 0.156852 -1.034756 -0.293759
我用以下任何一个交换了列级别:
# option one
df.columns = df.columns.reorder_levels([1,0])
# option two
df.columns = df.columns.swaplevel(0, 1)
这很有效,但如何在保持数据对齐的同时移动标签呢?
我尝试了以下内容:
df.columns = df.columns.set_labels([0,0,1,1,2,2], level=0).set_labels([0,1,0,1,0,1], level=1)
不幸的是,数据不随标签移动(即数据现在未对齐):
bar A B C
foo 1 2 1 2 1 2
2000-01-03 2.040867 -1.727071 0.126223 2.101799 1.811349 -0.003293
2000-01-04 -2.644979 0.156852 -1.034756 0.609625 -0.213968 -0.293759
我有很多东西,包括重新索引,但无济于事。
编辑:这只是一个比喻性的例子,但实际上我的数据在列轴的第二级(交换后)中包含分类标签[Min,Max,Single],即:< / p>
arrays = [['Max', 'Min', 'Single']*3, np.repeat(['A', 'B', 'C'], 3)]
columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar'])
df = pd.DataFrame(np.random.randn(2,9),
columns=columns,
index= pd.date_range('20000103',periods=2))
print(df)
foo Max Min Single Max Min Single Max Min Single
bar A A A B B B C C C
2000-01-03 -0.004233 0.820975 1.481674 0.064850 -0.178978 -0.862092 0.136279 -0.517081 -1.557611
2000-01-04 0.835346 -0.403773 -0.035985 1.079355 1.780113 -1.037420 1.459070 -0.254668 -0.091501
df.columns = df.columns.swaplevel(0,1)
print(df)
bar A B C
foo Max Min Single Max Min Single Max Min Single
2000-01-03 -0.004233 0.820975 1.481674 0.064850 -0.178978 -0.862092 0.136279 -0.517081 -1.557611
2000-01-04 0.835346 -0.403773 -0.035985 1.079355 1.780113 -1.037420 1.459070 -0.254668 -0.091501
对于第二级,我想使用明确提供的订单:['Min', 'Max', 'Single']
。因此,按照@Primer的建议按字母顺序排序将不起作用。
答案 0 :(得分:1)
交换完需要使用.sort_index
的级别后,这将产生所需的结果。
这对我有用:
arrays = [[1, 2]*3, ['A', 'B', 'C']*2]
columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar'])
df = pd.DataFrame(pd.np.random.randn(2,6),
columns=columns,
index= pd.date_range('20000103',periods=2))
print(df)
foo 1 2 1 2 1 2
bar A B C A B C
2000-01-03 -1.165 0.901 0.466 -1.536 1.488 1.896
2000-01-04 1.179 -0.180 -1.071 1.054 -0.403 1.222
df.columns = df.columns.swaplevel(0, 1)
df.sort_index(1, inplace=True)
print df
bar A B C
foo 1 2 1 2 1 2
2000-01-03 -1.165 -1.536 1.488 0.901 0.466 1.896
2000-01-04 1.179 1.054 -0.403 -0.180 -1.071 1.222
<强>更新强>:
Categorical
具有ordered
属性,您可以使用该属性设置所需的任何订单,然后使用.sort_index
或.sort
对其进行排序。
以下是如何为foo
设置自定义订单的说明:
array1 = ['A', 'B']*3
array2 = ['Min', 'Max', 'Single']*2
columns = pd.MultiIndex.from_tuples(zip(array2, array1), names=['foo', 'bar'])
df = pd.DataFrame(pd.np.random.randn(2,6),
columns=columns,
index= pd.date_range('20000103',periods=2))
print df
foo Single Max Min Single Max Min
bar A B A B A B
2000-01-03 0.098 0.583 -0.399 0.370 -1.307 1.658
2000-01-04 -0.118 -0.680 0.666 -0.461 -1.334 -1.347
# Here is we extract foo column just to illustrate that it is Categorical and sorted in 'wrong' order:
df = df.stack().stack().reset_index().rename(columns={'level_0':'date',0:'val'})
df['foo'] = df.foo.astype('category')
print df.foo
0 Max
1 Min
2 Single
3 Max
4 Min
5 Single
6 Max
7 Min
8 Single
9 Max
10 Min
11 Single
Name: foo, dtype: category
Categories (3, object): [Max, Min, Single]
请注意最后一行中的列表 - 如果您在其上调用.sort
,则会按顺序(按字母顺序排列)对其进行排序。
现在我们将使用新订单重新定义此列:
df['foo'] = pd.Categorical(pd.np.asarray(df.foo), categories=['Min','Single','Max'], ordered=True)
print df.foo
0 Max
1 Min
2 Single
3 Max
4 Min
5 Single
6 Max
7 Min
8 Single
9 Max
10 Min
11 Single
Name: foo, dtype: category
Categories (3, object): [Min < Single < Max]
请注意,在最后一行中,列表现在显示新订单,<
符号表明这是一个ordered
Categorical
系列。
当您在其上调用.sort
时,它将按所示顺序排序。
希望这有帮助。