pandas 列的 MultiIndex select 级别 0(外部)和级别 1(内部)的列

pandas MultiIndex on columns select columns from level 0 (outside) as well as level 1 (inside)

使用虚拟数据帧:

import pandas as pd

df = pd.DataFrame({'dt':['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-03', '2020-01-01', '2020-01-02', '2020-01-03', '2020-01-03'], 'group':['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'], 'bar':[1,2,3, 4, 1,2,3, 4], 'baz':[3,4,5, 6, 3,4,5, 6]})
df = df.groupby(['dt', 'group']).describe()

即我希望能够selectdf[['dt', 'group', ('bar', '25%'), , ('bar', '25%'), , ('bar', '25%')]]

如何执行此多级 select离子?

我的最终目标是能够绘制每个类别随时间变化的百分位数,其中每个类别描述一种颜色:

import seaborn as sns; sns.set()
sns.lineplot(data=df.reset_index()['baz'][['25%', '50%', '75%']], hue='group')

但是,在剩余的数据框中,没有留下任何关于组的信息。

I.e. I want to be able to select df[['dt', 'group', ('bar', '25%'), , ('bar', '25%'), , ('bar', '25%')]].

您可以执行以下操作:

df.reset_index()[[('dt', ""), ('group', ""), ('bar', '25%'), ('bar', '50%')]]

输出:

           dt group  bar     
                     25%  50%
0  2020-01-01     a  1.0  1.0
1  2020-01-02     a  2.0  2.0
2  2020-01-03     b  3.0  3.5

至于图表,在我看来你正在尝试绘制一个具有 4 个维度的图...(x->dt,y->dataframe 值,hue-> 对应于每个组,然后你有每个百分位列,例如 ('bar', '25%')('bar', '50%'))。目前尚不清楚您要如何区分情节中的 ('bar', '25%')('bar', '50%')。也许您期待 6 个单独的图(3 个百分位数 * 2 列 [bar, baz]),在这种情况下这可能会有所帮助:

sns.lineplot(data=df.reset_index(), x="dt", y=("bar", '25%'), hue='group')

不确定这是否是您想要的:

 #assigned outcome to a different variable
 res = df.groupby(['dt', 'group']).describe()

#create a slicer, makes it easier to slice the multiIndex
idx = pd.IndexSlice

res.loc[idx[:],idx['bar',['25%','50%','75%']]]

您可以使用它来获得相同的结果

res.loc(axis=1)['bar',['25%','50%','75%']]


                        bar
                25% 50% 75%
   dt   group           
2020-01-01  a   1.0 1.0 1.0
2020-01-02  a   2.0 2.0 2.0
2020-01-03  b   3.0 3.5 4.0

或横截面切片:

res.xs('bar',level=0,axis=1).filter(['25%','50%','75%'])

                25% 50% 75%
   dt   group           
2020-01-01  a   1.0 1.0 1.0
2020-01-02  a   2.0 2.0 2.0
2020-01-03  b   3.0 3.5 4.0

另一种剥猫皮的方法:

print (df["bar"].filter(like="%"))

                  25%  50%  75%
dt         group               
2020-01-01 a      1.0  1.0  1.0
2020-01-02 a      2.0  2.0  2.0
2020-01-03 b      3.0  3.5  4.0