在列上有条件的熊猫多索引选择

时间:2020-01-09 17:08:21

标签: python pandas multi-index

我无法在多索引数据帧上进行过滤。

import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randn(6, 6), 
  columns=pd.MultiIndex.from_arrays((['Team_1','Team_1','Team_1','Team_1','Team_1','Team_1'],
  ['A','A','A','B','B','B'], ['a', 'b', 'c', 'a', 'b', 'c'])))

如下所示:

     Team_1                                                  
          A                             B                    
          a         b         c         a         b         c
0  1.663478  1.121481 -0.675905 -1.286932 -0.713381  0.835101
1  0.076587  1.334063 -1.804435 -0.892450 -0.349493 -1.448643
2  0.485618  0.675481 -0.488584 -0.354583  1.827532 -1.184389
3 -0.531397 -0.145830 -1.143331 -0.871459 -0.009081 -1.741627
4  0.355948 -2.275475  0.543201 -0.099087 -1.114334 -1.248298
5  1.448409 -0.974127  2.004364 -0.880845  1.195134  0.392949

我想要的是输出df,其中ab有一些要求,如果两者都为true,则还要包括c列。例如,给定剪切为a>0b<0的输出想要

     Team_1                                                  
          A                             B                    
          a         b         c         a         b         c
0  1.663478       NaN       NaN       NaN -0.713381       NaN
1  0.076587       NaN       NaN       NaN -0.349493       NaN
2  0.485618       NaN       NaN -0.354583       NaN       NaN
3       NaN -0.145830       NaN       NaN -0.009081       NaN
4  0.355948 -2.275475  0.543201       NaN -1.114334       NaN
5  1.448409 -0.974127  2.004364       NaN       NaN       NaN

首先,我可以进行基本选择(df.iloc[:, df.columns.get_level_values(2) == 'a'] > 0),但不确定从那里去哪里。

2 个答案:

答案 0 :(得分:2)

使用xs选择列并删除该级别的MultiIndex。那么'c'是前两个掩码之间的&检查。 concatkeys一起添加标签,然后使用此完整的布尔掩码将原始DataFrame子集化。

m1 = df.xs('a', level=2, axis=1).gt(0)  # a > 0
m2 = df.xs('b', level=2, axis=1).lt(0)  # b < 0
m = pd.concat([m1, m2, m1&m2], axis=1, keys=['a', 'b', 'c']).reorder_levels([1,2,0], axis=1)

df[m]   # used np.random.seed(13) in creation.
     Team_1                                            
          A                             B              
          a         b         c         a         b   c
0       NaN       NaN       NaN  0.451812       NaN NaN
1  1.350188       NaN       NaN       NaN -0.788989 NaN
2  0.562847 -0.243326  0.913741  0.317351       NaN NaN
3  0.606289 -0.026772 -0.984161  1.190705       NaN NaN
4       NaN       NaN       NaN       NaN       NaN NaN
5  0.490872       NaN       NaN       NaN       NaN NaN

答案 1 :(得分:2)

另一种选择是使用stack / unstack

result = (
    df.stack(level=[0, 1])
      .assign(
          c=lambda df: np.where(
              (df["a"] > 0) & (df["b"] < 0),
              df["c"], np.nan
          )
          a=lambda df: np.where(
              df["a"] > 0, df["a"], np.nan
          ),
          b=lambda df: np.where(
              df["b"] < 0, df["b"], np.nan
          )
      ).unstack(level=[1, 2])
      .reorder_levels([1, 2, 0], axis=1)
      .sort_index(level=1, axis=1)
)

如果我们以df开头,如下所示:

     Team_1                                                  
          A                             B                    
          a         b         c         a         b         c
0  0.622728 -1.059337  0.154738 -1.118633  0.336635  1.173941
1  0.166443  0.236547  0.690746  0.169085 -0.107237 -0.539768
2 -1.270542  0.525559  0.335747  0.455872 -0.523938  0.508105
3  1.964184  0.281073  0.567805  0.012256  2.773986 -0.900674
4  1.997804 -0.621523 -0.253128  1.867092  0.134846  2.729482
5  0.860470 -0.293951 -1.581081 -2.014744  1.357025 -1.007692

输出result将是:

     Team_1                                                  
          A                             B                    
          a         b         c         a         b         c
0  0.622728 -1.059337  0.154738       NaN       NaN       NaN
1  0.166443       NaN       NaN  0.169085 -0.107237 -0.539768
2       NaN       NaN       NaN  0.455872 -0.523938  0.508105
3  1.964184       NaN       NaN  0.012256       NaN       NaN
4  1.997804 -0.621523 -0.253128  1.867092       NaN       NaN
5  0.860470 -0.293951 -1.581081       NaN       NaN       NaN