Let's be given the following dataframe with multi-index columns
import numpy as np
import pandas as pd
a = ['i', 'ii']
b = list('abc')
mi = pd.MultiIndex.from_product([a,b])
df = pd.DataFrame(np.arange(100,100+len(mi)*3).reshape([-1,len(mi)]),
columns=mi)
print(df)
# i ii
# a b c a b c
# 0 100 101 102 103 104 105
# 1 106 107 108 109 110 111
# 2 112 113 114 115 116 117
Using .loc[] and pd.IndexSlice I try to select the columns 'c' and 'b', in that very ordering.
idx = pd.IndexSlice
df.loc[:, idx[:, ['c','b']]]
However, if I look at the output, the requested ordering is not respected!
# i ii
# b c b c
# 0 101 102 104 105
# 1 107 108 110 111
# 2 113 114 116 117
Here are my questions:
- Why is the ordering not preserved by pandas? I consider this pretty dangerous, because the list
['c', 'b']implies an ordering from a user point of view. - How to access the columns via
loc[]while preserving the ordering at the same time?
Update: (02.02.2020)
The issue has been identified as pandas bug. In the process of fixing it, this related issue has been identified, which addresses a semantic ambiguity for expressions like df.loc[:, pd.IndexSlice[:, ['c','b']]].
In the meantime, the problem can be circumvented using the approach described in the accepted answer.