【问题标题】:Pandas 1.0.1 - how to index a DataFrame with MultiIndex using a list containing a slicerPandas 1.0.1 - 如何使用包含切片器的列表使用 MultiIndex 索引 DataFrame
【发布时间】:2020-03-29 04:38:58
【问题描述】:

作为示例数据集 -

In [12]: import numpy as np; import pandas as pd                                                     

In [24]: data_raw = pd.DataFrame([  
    ...:      ...: {'frame': 1, 'face': np.NaN, 'lmark': np.NaN, 'x': np.NaN, 'y': np.NaN},  
    ...:      ...: {'frame': 197, 'face': 0, 'lmark': 1, 'x': 969, 'y': 737},  
    ...:      ...: {'frame': 197, 'face': 0, 'lmark': 2, 'x': 969, 'y': 740},  
    ...:      ...: {'frame': 197, 'face': 0, 'lmark': 3, 'x': 970, 'y': 744},  
    ...:      ...: {'frame': 197, 'face': 0, 'lmark': 4, 'x': 972, 'y': 748},  
    ...:      ...: {'frame': 197, 'face': 0, 'lmark': 5, 'x': 973, 'y': 752},  
    ...:      ...: {'frame': 300, 'face': 0, 'lmark': 1, 'x': 745, 'y': 367},   
    ...:      ...: {'frame': 300, 'face': 0, 'lmark': 2, 'x': 753, 'y': 411},   
    ...:      ...: {'frame': 300, 'face': 0, 'lmark': 3, 'x': 759, 'y': 455},  
    ...:      ...: {'frame': 301, 'face': 0, 'lmark': 1, 'x': 741, 'y': 364},    
    ...:      ...: {'frame': 301, 'face': 0, 'lmark': 2, 'x': 746, 'y': 408},    
    ...:      ...: {'frame': 301, 'face': 0, 'lmark': 3, 'x': 750, 'y': 452}]).set_index(['frame', 'face', 'lmark'])                                        

在 Pandas 1.0.3 中,我可以过滤掉上面 lmark > 3 的 DataFrame 行,并使用以下内容 -

data_filtered = data_raw.loc[(slice(None), slice(None), [np.NaN, slice(3)]), :]

但在 Pandas 1.1.0 中,相同的语句失败并显示

TypeError: unhashable type: 'slice'

显然此更改是由 design 完成的。

在这种情况下,我如何过滤掉 lmark > 3 以下的 DataFrame 行?

【问题讨论】:

    标签: pandas indexing


    【解决方案1】:

    使用IndexSliceslice 选择只能在某些版本中正确工作,所以我建议使用另一种方法,按条件选择:

    DataFrame.query过滤:

    vals = [np.nan,1,2,3]
    df = data_raw.query('lmark in @vals')
    

    Index.isin:

    vals = [np.nan,1,2,3]
    df = data_raw[data_raw.index.get_level_values('lmark').isin(vals)]
    

    如果想选择所有没有>3的值:

    df = data_raw[~(data_raw.index.get_level_values('lmark') > 3)]
    

    或所有

    i = data_raw.index.get_level_values('lmark')
    df = data_raw[(i <= 3) | i.isna()]
    

    GroupBy.head 为第一级的前 3 行:

    df = data_raw.groupby(level=0).head(3)
    

    print (df)
                          x      y
    frame face lmark              
    1     NaN  NaN      NaN    NaN
    197   0.0  1.0    969.0  737.0
               2.0    969.0  740.0
               3.0    970.0  744.0
    300   0.0  1.0    745.0  367.0
               2.0    753.0  411.0
               3.0    759.0  455.0
    301   0.0  1.0    741.0  364.0
               2.0    746.0  408.0
               3.0    750.0  452.0
    

    【讨论】:

    • 我更喜欢df = data_raw[~(data_raw.index.get_level_values('lmark') &gt; 3)],谢谢
    【解决方案2】:

    注意:我不太确定 Pandas 1.0 之前的版本。如果您必须处理低于 Pandas 1.0 的版本,@jezrael 的解决方案要稳定得多。

    我不知道这是否符合您的用例,您只希望 lmark 上的行数少于 3:Multi-Index Slicing

    #allows for easier slicing than Slice(None)
    idx = pd.IndexSlice
    
    #list the data u want to keep ... including np.nan
    data_raw.loc[idx[:,:,[np.nan,1,2,3]],:]
    
                               x    y
    frame   face    lmark                   
    1        NaN    NaN      NaN    NaN
    197     0.0     1.0     969.0   737.0
                    2.0     969.0   740.0
                    3.0     970.0   744.0
    300     0.0     1.0     745.0   367.0
                    2.0     753.0   411.0
                    3.0     759.0   455.0
    301     0.0     1.0     741.0   364.0
                    2.0     746.0   408.0
                    3.0     750.0   452.0
    

    【讨论】:

    • data_raw.loc[idx[:,:,:3],:] 过滤掉行 lmark > 3 和 lmark = np.NaN。我只想过滤掉行lmark > 3
    • 编辑了代码。让我知道这是不是你的想法
    • @sammywemmy - 嗯,对我来说你的代码省略了NaNs,所以indexSlice也是版本依赖...
    • @jezrael,OP 使用的是 1.1.0 版。编辑代码以包含 NaN
    • 这个答案也是正确的,但在更一般的情况下 - 用诸如[np.nan,1,2,3, ...N] 之类的显式索引值替换切片器会很不方便。
    猜你喜欢
    • 2017-03-28
    • 2018-12-29
    • 2023-04-01
    • 2012-10-02
    • 2019-03-23
    • 2017-05-08
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    相关资源
    最近更新 更多