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

时间:2014-08-10 00:56:57

标签: python filter pandas indexing

我有下表:

注意: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

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

6 个答案:

答案 0 :(得分:43)

您可以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

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

请注意,您的数据中包含'upland'而不是'Upland'

答案 1 :(得分:22)

另一种(也许更干净)的方式可能是这样:

print(df[df.index.isin(['Lake', 'River', 'Upland'], level=1)])

参数level指定索引号(以0开头)或索引名称(此处为level='PBL_AWI'

答案 2 :(得分:3)

另外(来自here):

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

......用作

df.filter_by({'PBL_AWI' : ['Lake', 'River', 'Upland']})

(未经过Panels和更高维度元素测试,但我确实希望它可以工作)

答案 3 :(得分:1)

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

df.filter(regex='Lake|River|Upland',axis=0)

enter image description here

如果你转置它,并尝试过滤列(默认情况下轴=1),它也能正常工作:

df.T.filter(regex='Lake|River|Upland')

enter image description here

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

upland = re.compile('Upland', re.IGNORECASE)
df.filter(regex=upland ,axis=0)

enter image description here

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

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

答案 4 :(得分:0)

这是对所提问题的一个细微变化的答案,该问题可能会节省其他人一点时间。如果您要查找与您不知道确切值的标签匹配的通配符类型,则可以使用以下方式:

q_labels = [ label for label in df.index.levels[1] if label.startswith('Q') ]
new_df = df[ df.index.isin(q_labels, level=1) ]

答案 5 :(得分:0)

使用 .loc 的更简单方法是

df.loc[(slice(None),['Lake', 'River', 'Upland'])]

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

过滤二级索引