簡體   English   中英

過濾多索引中的多個項目 Python 熊貓 dataframe

[英]Filtering multiple items in a multi-index Python Panda dataframe

我有下表:

NSRCODE  PBL_AWI          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

注意: NSRCODEPBL_AWI都是索引。

如何在PBL_AWI列中搜索值? 例如,我想保留值['Lake', 'River', 'Upland']

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

另一種(可能更清潔)的方式可能是這個:

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

參數level指定索引號(以 0 開頭)或索引名稱(此處: level='PBL_AWI'

另外(從這里):

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']})

(未經面板和更高維度元素的測試,但我確實希望它能夠工作)

df。 filter(regex=...,axis=...)更加簡潔,因為它適用於 index=0 和 column=1 軸。 您無需擔心級別,並且您可以使用正則表達式偷懶。 索引過濾器的完整示例:

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

在此處輸入圖片說明

如果您轉置它,並嘗試過濾列(默認情況下軸 = 1),它也可以正常工作:

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

在此處輸入圖片說明

現在,使用正則表達式,您還可以輕松解決 Upland 的大寫小寫問題:

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

在此處輸入圖片說明

這是讀取上述輸入表的命令:

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

您還可以使用query

In [9]: df.query("PBL_AWI == ['Lake', 'River', 'Upland']")
Out[9]: 
                     Area
NSRCODE PBL_AWI          
CM      Lake     57124.82
        River     1603.91
LBH     Lake    258046.51
        River    44262.81

但是,由於區分大小寫,將找不到“upland”(小寫)。 因此我建議使用fullmatch並設置case=False

In [10]: df.query("PBL_AWI.str.fullmatch('Lake|River|Upland', case=False).values")
Out[10]: 
                       Area
NSRCODE PBL_AWI            
CM      Lake       57124.82
        River       1603.91
        upland   2701289.27
LBH     Lake      258046.51
        River      44262.81
        upland  23843453.64

這是對所問問題的一個輕微變體的回答,可能會為其他人節省一點時間。 如果您正在尋找與您不知道確切值的標簽的通配符類型匹配,您可以使用以下內容:

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

使用.loc一種更簡單的方法是

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

slice(None)表示不對第一級索引進行過濾。 我們可以使用值列表['Lake', 'River', 'Upland']過濾二級索引

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM