以特定格式访问MultiIndex



我有以下数据框架,

df = pd.DataFrame(np.random.randint(0,1000, (5,6)), 
columns = pd.MultiIndex.from_product([['CPC', 'Conversions'], ['April', 'June', 'May']])).rename_axis(index = {None : 'idx'})
df
CPC                 Conversions          
April June  May     April June  May
idx                                      
0     663  964  971      663   76  927
1     405  217  754      370  306   34
2     474  229  664      354   66  885
3      73  538  139      417  876  855
4     619  618  618      455  134  805

我想以正确的格式访问月份列级别,所以我这样做了

df.loc[:, (slice(None), ['April', 'May', 'June'])]
CPC Conversions   CPC Conversions   CPC Conversions
April       April   May         May  June        June
idx                                                     
0      806         202   963         975   110          55
1      263         884   442         563   216         694
2      462         361   780         412   858         670
3      742         756   525          33   477         826
4      579         332    91         802   829         231

当我使用两个月而不是三个月(见下文)时,结果却很好,这很奇怪

df.loc[:, (slice(None), ['April', 'May'])]
CPC      Conversions     
April  May       April  May
idx                            
0       856  619         180  593
1        64  403         929   80
2       973  285         803  967
3       769  405         701  267
4       940  368         863  717

谁能告诉我什么是错误的,这在我看来buggy

目前我正在做的是创建一个MultiIndex.from_product(就像我用来创建这个例子一样)与有序的月份,并用它替换现有的列。但是,我不想这样做,因为其他列级别可能会随着时间的推移而改变。

这不是bug,只是意外:

>>> df.columns.levels
FrozenList([['CPC', 'Conversions'], ['April', 'June', 'May']])
>>> df.columns.codes
FrozenList([[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]])
>>> df.columns.is_monotonic
True

我们可以看到'April'的代码为0,'June'的代码为1,'May'的代码为2。

现在按秒级对数据帧进行切片:

# Your code (unordered codes)
>>> df.loc[:, (slice(None), ['April', 'May', 'June'])]
CPC Conversions  CPC Conversions  CPC Conversions
April       April  May         May June        June
...

,但是如果你根据有序的代码切片你的数据帧,它工作如预期:

>>> df.loc[:, (slice(None), ['April', 'June', 'May'])]
CPC           Conversions          
April June  May       April June  May
...

检查一些属性:

>>> df.loc[:, (slice(None), ['April', 'May', 'June'])].columns.is_monotonic
False
>>> df.loc[:, (slice(None), ['April', 'June', 'May'])].columns.is_monotonic
True
>>> df.loc[:, (slice(None), ['April', 'May', 'June'])].columns.codes
FrozenList([[0, 1, 0, 1, 0, 1], [0, 0, 2, 2, 1, 1]])
>>> df.loc[:, (slice(None), ['April', 'June', 'May'])].columns.codes
FrozenList([[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]])

如果你在你的切片之后使用sort_index,数据帧被排序为它的创建:

>>> df.loc[:, (slice(None), ['April', 'May', 'June'])].sort_index(axis=1)
CPC           Conversions          
April June  May       April June  May
...

基于codes排序MultiIndex

您可以使用df.reindex():

对列进行排序
cols = ['April', 'May', 'June']
new_cols = df.columns.reindex(cols, level=1)
df.reindex(columns=new_cols[0])

不创建新变量:

df.reindex(columns=['April', 'May', 'June'], level=1)

最新更新