【问题标题】:Filter rows from DataFrame by multi-index column slice predicate通过多索引列切片谓词过滤 DataFrame 中的行
【发布时间】:2019-03-17 10:36:59
【问题描述】:

我有一个数据框,其列的多索引定义如下:

import numpy as np
import pandas as pd
index = range(4)
columns = pd.MultiIndex.from_product([
    ['A0', 'B0'],
    ['A1', 'B1'],
    ['A2', 'B2']
])

data = np.random.rand(len(index), len(columns))
df = pd.DataFrame(data, index=index, columns=columns)

这给了我类似的东西:

         A0                                      B0                              
         A1                  B1                  A1                  B1          
         A2        B2        A2        B2        A2        B2        A2        B2
0  0.523564  0.270243  0.881117  0.760946  0.687436  0.318483  0.963247  0.161210
1  0.141363  0.563427  0.242174  0.966277  0.382161  0.486944  0.417305  0.513510
2  0.832275  0.036995  0.510963  0.112446  0.069597  0.490321  0.022453  0.643659
3  0.601649  0.705902  0.735125  0.506853  0.666612  0.533352  0.484133  0.069325

我现在想过滤任何B2 列的值低于阈值的所有行,例如0.05。我做了以下事情:

df_filtered = df[df.loc[:, (slice(None), slice(None), 'B2')] < 0.05]

但这给了我以下信息:

   A0                    B0            
   A1            B1      A1      B1    
   A2        B2  A2  B2  A2  B2  A2  B2
0 NaN NaN       NaN NaN NaN NaN NaN NaN
1 NaN NaN       NaN NaN NaN NaN NaN NaN
2 NaN  0.036995 NaN NaN NaN NaN NaN NaN
3 NaN NaN       NaN NaN NaN NaN NaN NaN

这不是我想要的,因为:

  • 该行的值以某种方式映射到NaN。我想保留原始行内容。
  • 返回所有行。我只想要B2 的任何值低于0.05 的行,在这个CAS 中只有index=2 的行。

我怎样才能做到这一点?

【问题讨论】:

    标签: python pandas slice multi-index


    【解决方案1】:

    使用DataFrame.any 至少检查每列一个True 并添加reindex 以追加MultiIndex 的缺失级别:

    np.random.seed(456)
    
    import numpy as np
    import pandas as pd
    index = range(4)
    columns = pd.MultiIndex.from_product([
        ['A0', 'B0'],
        ['A1', 'B1'],
        ['A2', 'B2']
    ])
    
    data = np.random.rand(len(index), len(columns))
    df = pd.DataFrame(data, index=index, columns=columns)
    print (df)
             A0                                      B0                      \
             A1                  B1                  A1                  B1   
             A2        B2        A2        B2        A2        B2        A2   
    0  0.248756  0.163067  0.783643  0.808523  0.625628  0.604114  0.885702   
    1  0.181105  0.150169  0.435679  0.385273  0.575710  0.146091  0.686593   
    2  0.569999  0.645701  0.723341  0.680671  0.180917  0.118158  0.242734   
    3  0.360068  0.146042  0.542723  0.857103  0.200212  0.134633  0.213594   
    
    
    
             B2  
    0  0.759117  
    1  0.468804  
    2  0.008183  
    3  0.973156 
    

    mask = ((df.loc[:, (slice(None), slice(None), 'B2')] < 0.05)
               .any()
               .reindex(df.columns, fill_value=False))
    print (mask)
    A0  A1  A2    False
            B2    False
        B1  A2    False
            B2    False
    B0  A1  A2    False
            B2    False
        B1  A2    False
            B2     True
    dtype: bool
    
    df = df.loc[:, mask]
    print (df)
             B0
             B1
             B2
    0  0.759117
    1  0.468804
    2  0.008183
    3  0.973156
    

    对于行的解决方案更简单 - 使用 DataFrame.anyaxis=1 来检查每行至少一个 True

    mask = (df.loc[:, (slice(None), slice(None), 'B2')] < 0.05).any(axis=1)
    print (mask)
    0    False
    1    False
    2     True
    3    False
    dtype: bool
    
    df = df[mask]
    print (df)
             A0                                      B0                      \
             A1                  B1                  A1                  B1   
             A2        B2        A2        B2        A2        B2        A2   
    2  0.569999  0.645701  0.723341  0.680671  0.180917  0.118158  0.242734   
    
    
    
             B2  
    2  0.008183  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-24
      • 2013-08-09
      • 2018-02-28
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多