[英]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
注意: NSRCODE
和PBL_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.