维护Pandas Multiindex DataFrame的顺序

时间:2017-11-05 13:40:00

标签: python pandas dataframe multi-index

我有以下数据框:

import pandas as pd
import numpy as np

lvl0 = ['foo', 'bar']
lvl1 = ['x', 'y']

cols = pd.MultiIndex.from_product([lvl0, lvl1])
df = pd.DataFrame(np.random.rand(3,4), columns=cols)

产生:

    foo                     bar
    x           y           x           y
0   0.885461    0.613618    0.404915    0.855922
1   0.096102    0.161894    0.786328    0.805401
2   0.035256    0.476391    0.834996    0.826073

我想添加另一列,但是当我这样做时,它会放在最后:

df [('foo','z')] = np.random.rand(3)

    foo                     bar                     foo
    x           y           x           y           z
0   0.885461    0.613618    0.404915    0.855922    0.782947
1   0.096102    0.161894    0.786328    0.805401    0.898574
2   0.035256    0.476391    0.834996    0.826073    0.407470

虽然我希望它通过lvl0列进行可视化分组,如下所示:

    foo                                 bar
    x           y           z           x           y
0   0.885461    0.613618    0.782947    0.404915    0.855922
1   0.096102    0.161894    0.898574    0.786328    0.805401
2   0.035256    0.476391    0.407470    0.834996    0.826073

最好的方法是什么?我考虑过事先检查df.columns,按原样列出lvl0列名,然后重新分配df,如:

old_col_order = some_sort_of_columns_gymnastics()
df = df[old_col_order]

但这些看起来很混乱,我不能成为第一个想要订购新列的人。我也考虑使用sort_index,但我的原始订单也不是字典顺序,所以我仍然必须以某种方式找到原始订单。

1 个答案:

答案 0 :(得分:2)

In [215]: new_pos = df.columns.get_loc(('foo','y')) + 1

In [216]: df.insert(new_pos, ('foo','z'), np.random.rand(3))

In [217]: df
Out[217]:
        foo                           bar
          x         y         z         x         y
0  0.368823  0.820497  0.192941  0.174843  0.060076
1  0.111381  0.986995  0.163618  0.517629  0.836983
2  0.431267  0.058645  0.223167  0.793508  0.936183

或者如果我们不知道最后一个子列(在我们的例子中是y):

In [250]: df.insert(len(df.columns.to_series().loc['foo']), ('foo','z'), np.random.rand(3))

In [251]: df
Out[251]:
        foo                           bar
          x         y         z         x         y
0  0.368823  0.820497  0.294450  0.174843  0.060076
1  0.111381  0.986995  0.521423  0.517629  0.836983
2  0.431267  0.058645  0.264008  0.793508  0.936183

演示 - 让我们在z列中添加bar子列:

In [292]: x
Out[292]:
        foo                 bar                 baz
          x         y         x         y         x         y
0  0.368823  0.820497  0.174843  0.060076  0.368823  0.820497
1  0.111381  0.986995  0.517629  0.836983  0.111381  0.986995
2  0.431267  0.058645  0.793508  0.936183  0.431267  0.058645

In [293]: last_subcol = x.columns.to_series().loc['bar'].index[-1]

In [294]: last_subcol
Out[294]: 'y'

In [295]: new_pos = df.columns.get_loc(('bar',last_subcol)) + 1

In [296]: x.insert(new_pos, ('bar','z'), np.random.rand(3))

In [297]: x
Out[297]:
        foo                 bar                           baz
          x         y         x         y         z         x         y
0  0.368823  0.820497  0.174843  0.060076  0.694670  0.368823  0.820497
1  0.111381  0.986995  0.517629  0.836983  0.722398  0.111381  0.986995
2  0.431267  0.058645  0.793508  0.936183  0.126137  0.431267  0.058645