按多指标级别的子集选择

Selecting by subset of multiindex level

玩具示例

假设我有下面显示的数据框 df

           C
L0 L1 L2    
0  w  P   11
      Q    9
      R   21
      S    4
   x  P    3
      Q    0
      R   23
      S   20
   y  P   19
      Q    0
      R    7
      S   13
   z  P   17
      Q    0
      R    5
      S    1
1  w  P    8
      Q    2
      R   12
      S    0
   x  P   22
      Q   14
      R    2
      S   18
   y  P    6
      Q    0
      R   16
      S   15
   z  P   10
      Q    0
      R    8
      S    0

注意df的行是用3级多索引索引的

我可以为L2级别的每个值找到C列的最小值,如下:

In [58]: df.groupby(level='L2').min()
Out[58]: 
    C
L2   
P   3
Q   0
R   2
S   0

类似地,以下表达式显示了 L2 的值,其中此最小值大于 0:

In [59]: df.groupby(level='L2').min() > 0
Out[59]: 
        C
L2       
P    True
Q   False
R    True
S   False

问题:我如何select原始数据帧df的行对应于L2的值,其中最小值的 C 大于 0?


在这个简单的示例中,问题归结为 select 计算 df 的行,其 L2 值为 'P''R'。因此,通过将 L2='P' 的行与 L2='R'.

的行连接起来,不难解决问题。

然而,在我想到的应用程序中,这样的解决方案变得笨拙,因为这里的 L2 级别有 ~2000 个值,其中大约一半的最小值大于 0。

因此,我正在寻找一种更具可扩展性的方法来解决这个 select离子问题。

数据

L0  L1  L2  C
0   w   P   11
0   w   Q   9
0   w   R   21
0   w   S   4
0   x   P   3
0   x   Q   0
0   x   R   23
0   x   S   20
0   y   P   19
0   y   Q   0
0   y   R   7
0   y   S   13
0   z   P   17
0   z   Q   0
0   z   R   5
0   z   S   1
1   w   P   8
1   w   Q   2
1   w   R   12
1   w   S   0
1   x   P   22
1   x   Q   14
1   x   R   2
1   x   S   18
1   y   P   6
1   y   Q   0
1   y   R   16
1   y   S   15
1   z   P   10
1   z   Q   0
1   z   R   8
1   z   S   0

这是一种方法

存储所需的 L2 个值

In [413]: m = df.groupby(level='L2').min() > 0

In [414]: m
Out[414]:
        C
L2
P    True
Q   False
R    True
S   False

使用,get_level_values(index_level_name).isin(to_be_filtered) 只过滤需要的值。

In [415]: df[df.index.get_level_values('L2').isin(m.loc[m.C, :].index)]
Out[415]:
           C
L0 L1 L2
0  w  P   11
      R   21
   x  P    3
      R   23
   y  P   19
      R    7
   z  P   17
      R    5
1  w  P    8
      R   12
   x  P   22
      R    2
   y  P    6
      R   16
   z  P   10
      R    8

这是另一种方式。使用、变换和子集选择

In [430]: df[(df.groupby(level='L2').transform('min') > 0).C]
Out[430]:
           C
L0 L1 L2
0  w  P   11
      R   21
   x  P    3
      R   23
   y  P   19
      R    7
   z  P   17
      R    5
1  w  P    8
      R   12
   x  P   22
      R    2
   y  P    6
      R   16
   z  P   10
      R    8

详情

In [416]: m.loc[m.C, :].index
Out[416]: Index([u'P', u'R'], dtype='object', name=u'L2')