过滤多索引Python Panda数据帧中的多个项目

Tri*_*ard 30 python indexing filter pandas

我有下表:

注意:NSRCODE和PBL_AWI都是索引

注意:%of area列将被填写,但尚未完成.

NSRCODE  PBL_AWI          Area           % Of Area
CM       BONS             44705.492941
         BTNN            253854.591990
         FONG             41625.590370
         FONS             16814.159680
         Lake             57124.819333
         River             1603.906642
         SONS            583958.444751
         STNN             45603.837177
         clearcut        106139.013930
         disturbed       127719.865675
         lowland         118795.578059
         upland         2701289.270193
LBH      BFNN            289207.169650
         BONS           9140084.716743
         BTNI             33713.160390
         BTNN          19748004.789040
         FONG           1687122.469691
         FONS           5169959.591270
         FTNI            317251.976160
         FTNN           6536472.869395
         Lake            258046.508310
         River            44262.807900
         SONS           4379097.677405
         burn regen      744773.210860
         clearcut         54066.756790
         disturbed       597561.471686
         lowland       12591619.141842
         upland        23843453.638117
Run Code Online (Sandbox Code Playgroud)

如何过滤掉"PBL_AWI"索引中的项目?例如,我想保留['Lake','River','Upland']

CT *_*Zhu 59

您可以get_level_values结合布尔切片.

In [50]:

print df[np.in1d(df.index.get_level_values(1), ['Lake', 'River', 'Upland'])]
                          Area
NSRCODE PBL_AWI               
CM      Lake      57124.819333
        River      1603.906642
LBH     Lake     258046.508310
        River     44262.807900
Run Code Online (Sandbox Code Playgroud)

同样的想法可以用许多不同的方式表达,例如 df[df.index.get_level_values('PBL_AWI').isin(['Lake', 'River', 'Upland'])]

请注意,您'upland'在数据中而不是'Upland'

  • 我发现第二个解决方案对于类似的问题很有用,选择多索引值大于给定数字的行:`df[df.index.get_level_values('level_name') > 1]`。 (2认同)
  • 第二个解决方案应该是答案,更清晰并且不需要 np. (2认同)

小智 40

另一种(可能更清洁)的方式可能是这个:

print(df[df.index.isin(['Lake', 'River', 'Upland'], level=1)])
Run Code Online (Sandbox Code Playgroud)

该参数level指定的索引号(从0开始)或索引名称(这里:level='PBL_AWI'

  • 在这种情况下,对这些问题已经有了丰富的讨论,如果受访者不想写关于该主题的教科书章节,我仍然发现这个答案很有用。 (3认同)

小智 26

一种更简单的方法.loc

df.loc[(slice(None),['Lake', 'River', 'Upland']),:]
Run Code Online (Sandbox Code Playgroud)

或系列

df.loc[(slice(None),['Lake', 'River', 'Upland'])]
Run Code Online (Sandbox Code Playgroud)

slice(None)表示对一级索引不进行过滤。我们可以使用值列表过滤二级索引['Lake', 'River', 'Upland']

  • 这应该是公认的答案:索引根据定义用于进行这种直接查找,而不需要创建中间布尔数组。 (6认同)
  • 起初对我不起作用,这是: `df.loc[(slice(None), ["Lake", "River", "Upland"]), :]` (2认同)

jed*_*edi 11

df。filter(regex=...,axis=...)更加简洁,因为它适用于index=0 和column=1 轴。你不需要担心级别,你可以用正则表达式来偷懒。索引过滤器的完整示例:

df.filter(regex='Lake|River|Upland',axis=0)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果你转置它,并尝试对列进行过滤(默认情况下 axis=1),它也可以工作:

df.T.filter(regex='Lake|River|Upland')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

现在,使用正则表达式,您还可以轻松修复 Upland 的大小写问题:

upland = re.compile('Upland', re.IGNORECASE)
df.filter(regex=upland ,axis=0)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这是读取上面输入表的命令:

df = pd.read_csv(io.StringIO(inpute_table), sep="\s{2,}").set_index(['NSRCODE', 'PBL_AWI'])


Pie*_*ton 5

另外(从这里):

def filter_by(df, constraints):
    """Filter MultiIndex by sublevels."""
    indexer = [constraints[name] if name in constraints else slice(None)
               for name in df.index.names]
    return df.loc[tuple(indexer)] if len(df.shape) == 1 else df.loc[tuple(indexer),]

pd.Series.filter_by = filter_by
pd.DataFrame.filter_by = filter_by
Run Code Online (Sandbox Code Playgroud)

...用作

df.filter_by({'PBL_AWI' : ['Lake', 'River', 'Upland']})
Run Code Online (Sandbox Code Playgroud)

(未经面板和更高维度元素的使用,但我希望它能正常工作)