1 回答

TA貢獻1786條經(jīng)驗 獲得超11個贊
多重索引/高級索引
注
該員額的結(jié)構(gòu)如下:
執(zhí)行部分中提出的問題將一個接一個地加以解決。 對于每個問題,將演示一個或多個用于解決該問題并獲得預(yù)期結(jié)果的方法。 注
對于有興趣了解更多功能、實現(xiàn)細節(jié)和其他相關(guān)信息的讀者,將包括S(與此類似)。這些注釋是通過瀏覽文檔和發(fā)現(xiàn)各種晦澀的特性,并根據(jù)我自己(無可否認是有限的)經(jīng)驗編寫的。
所有代碼示例都在 熊貓v0.23.4,python3.7..如果某些事情不清楚,或者實際上不正確,或者如果您沒有找到適用于您的用例的解決方案,請隨時建議編輯,在評論中要求澄清,或在適用的情況下打開一個新的問題。
DataFrame.loc
-標簽選擇的一般解決方案(+) pd.IndexSlice
對于涉及片的更復(fù)雜的應(yīng)用程序) DataFrame.xs
-從系列/DataFrame中提取特定的截面。 DataFrame.query
-動態(tài)指定切片和/或過濾操作(即,作為動態(tài)計算的表達式。比其他情況更適用于某些情況。亦見 這部分文檔 用于查詢多個索引。 使用 MultiIndex.get_level_values
(通常與 Index.isin
,特別是當(dāng)使用多個值進行篩選時)。在某些情況下,這也是相當(dāng)有用的。
問題1
如何選擇在“一級”中具有“a”的行? col one two a t 0 u 1 v 2 w 3
loc
df.loc[['a']]
TypeError: Expected tuple, got str
df.loc[('a', slice(None)), :]
.
xs
levels
axis
df.xs('a', level=0, axis=0, drop_level=False)# df.xs('a', drop_level=False)
drop_level=False
xs
query
:
df.query("one == 'a'")
"ilevel_0 == 'a'"
.
get_level_values
:
df[df.index.get_level_values('one') == 'a']# If your levels are unnamed, or if you need to select by position (not label),# df[df.index.get_level_values(0) == 'a']
此外,我怎樣才能降低輸出中的“一”級呢? col two t 0u 1v 2w 3
df.loc['a'] # Notice the single string argument instead the list.
df.xs('a', level=0, axis=0, drop_level=True)# df.xs('a')
drop_level
True
注
您可能會注意到,過濾后的DataFrame可能仍然具有所有級別,即使它們在打印出DataFrame時沒有顯示出來。例如, v = df.loc[['a']]print(v) col one two a t 0 u 1 v 2 w 3print(v.index)MultiIndex(levels=[['a', 'b', 'c', 'd'], ['t', 'u', 'v', 'w']], labels=[[0, 0, 0, 0], [0, 1, 2, 3]], names=['one', 'two'])
您可以使用 MultiIndex.remove_unused_levels
:v.index = v.index.remove_unused_levels()print(v.index)MultiIndex(levels=[['a'], ['t', 'u', 'v', 'w']], labels=[[0, 0, 0, 0], [0, 1, 2, 3]], names=['one', 'two'])
問題1b
如何將值為“t”的所有行分割為“二級”? col one two a t 0b t 4 t 8d t 12
slice()
:
df.loc[(slice(None), 't'), :]
pd.IndexSlice
idx = pd.IndexSlicedf.loc[idx[:, 't'], :]
注
為什么尾翼 :
縱橫交錯?這是因為 loc
可用于沿兩個軸( axis=0
或 axis=1
)。如果不明確說明要在哪個軸上進行切片,操作就變得模糊不清??吹侥莻€紅色的大盒子 切片文件 .
如果你想消除任何含糊不清的地方, loc
接受 axis
參數(shù): df.loc(axis=0)[pd.IndexSlice[:, 't']]
沒有 axis
參數(shù)(即,只需執(zhí)行 df.loc[pd.IndexSlice[:, 't']]
),切片被假定在列上,并且 KeyError
將在這種情況下提出。
這被記錄在 切片機 ..然而,為了這篇文章的目的,我們將明確指定所有的軸。
xs
df.xs('t', axis=0, level=1, drop_level=False)
query
df.query("two == 't'")# Or, if the first level has no name, # df.query("ilevel_1 == 't'")
get_level_values
df[df.index.get_level_values('two') == 't']# Or, to perform selection by position/integer,# df[df.index.get_level_values(1) == 't']
問題2
如何選擇與“一級”中的“b”和“d”項對應(yīng)的行? col one two b t 4 u 5 v 6 w 7 t 8d w 11 t 12 u 13 v 14 w 15
df.loc[['b', 'd']]
query
:
items = ['b', 'd']df.query("one in @items")# df.query("one == @items", parser='pandas')# df.query("one in ['b', 'd']")# df.query("one == ['b', 'd']", parser='pandas')
注
是的,默認的解析器是 'pandas'
但是,強調(diào)這個語法并不是傳統(tǒng)的python,這一點很重要。Pandas解析器生成一個與表達式略有不同的解析樹。這樣做是為了使某些操作更直觀地指定。欲知更多信息,請閱讀我在 熊貓動態(tài)表達評價的pd.val() .
get_level_values
+ Index.isin
:
df[df.index.get_level_values("one").isin(['b', 'd'])]
問題2b
如何得到“二級”中與“t”和“w”對應(yīng)的所有值? col one two a t 0 w 3b t 4 w 7 t 8d w 11 t 12 w 15
loc
pd.IndexSlice
.
df.loc[pd.IndexSlice[:, ['t', 'w']], :]
:
pd.IndexSlice[:, ['t', 'w']]
query
items = ['t', 'w']df.query("two in @items")# df.query("two == @items", parser='pandas') # df.query("two in ['t', 'w']")# df.query("two == ['t', 'w']", parser='pandas')
get_level_values
Index.isin
df[df.index.get_level_values('two').isin(['t', 'w'])]
問題3
如何檢索橫截面,即具有索引的特定值的單個行 df
?具體而言,如何檢索 ('c', 'u')
,由 col one two c u 9
loc
df.loc[('c', 'u'), :]
df.loc[pd.IndexSlice[('c', 'u')]]
注
此時,您可能會遇到 PerformanceWarning
看起來是這樣的: PerformanceWarning: indexing past lexsort depth may impact performance.
這只意味著索引沒有排序。熊貓取決于被排序的索引(在這種情況下,按字典順序,因為我們處理的是字符串值),以便進行最佳搜索和檢索。一個快速的解決方法是預(yù)先使用以下方法對DataFrame進行排序 DataFrame.sort_index
..如果您計劃同時執(zhí)行多個這樣的查詢,那么從性能的角度來看,這是特別可取的: df_sort = df.sort_index()df_sort.loc[('c', 'u')]
您也可以使用 MultiIndex.is_lexsorted()
若要檢查索引是否已排序,請執(zhí)行以下操作。此函數(shù)返回 True
或 False
因此。您可以調(diào)用此函數(shù)來確定是否需要額外的排序步驟。
xs
df.xs(('c', 'u'))
query
df.query("one == 'c' and two == 'u'")
get_level_values
m1 = (df.index.get_level_values('one') == 'c')m2 = (df.index.get_level_values('two') == 'u')df[m1 & m2]
問題4
如何選擇與 ('c', 'u')
,和 ('a', 'w')
?col one two c u 9a w 3
loc
df.loc[[('c', 'u'), ('a', 'w')]]# df.loc[pd.IndexSlice[[('c', 'u'), ('a', 'w')]]]
query
cses = [('c', 'u'), ('a', 'w')]levels = ['one', 'two']# This is a useful check to make in advance.assert all(len(levels) == len(cs) for cs in cses) query = '(' + ') or ('.join([ ' and '.join([f"({l} == {repr(c)})" for l, c in zip(levels, cs)]) for cs in cses]) + ')'print(query)# ((one == 'c') and (two == 'u')) or ((one == 'a') and (two == 'w'))df.query(query)
問題5
如何檢索與“一級”中的“a”或“二級”中的“t”對應(yīng)的所有行? col one two a t 0 u 1 v 2 w 3b t 4 t 8d t 12
loc
df.loc[pd.IndexSlice['a', 't']]
df.loc[pd.IndexSlice[('a', 't')]]
pd.concat
pd.concat([ df.loc[['a'],:], df.loc[pd.IndexSlice[:, 't'],:]]) col one two a t 0 u 1 v 2 w 3 t 0 # Does this look right to you? No, it isn't!b t 4 t 8d t 12
v = pd.concat([ df.loc[['a'],:], df.loc[pd.IndexSlice[:, 't'],:]])v[~v.index.duplicated()]
query
df.query("one == 'a' or two == 't'")
get_level_values
m1 = (df.index.get_level_values('one') == 'c')m2 = (df.index.get_level_values('two') == 'u')df[m1 | m2]
問題6
如何分割特定的截面?對于“a”和“b”,我想選擇所有具有子級別“u”和“v”的行,對于“d”,我想選擇具有子級別“w”的行。 col one two a u 1 v 2b u 5 v 6d w 11 w 15
loc
keys = [('a', 'u'), ('a', 'v'), ('b', 'u'), ('b', 'v'), ('d', 'w')]df.loc[keys, :]
concat
pd.concat([ df.loc[(('a', 'b'), ('u', 'v')), :], df.loc[('d', 'w'), :] ], axis=0)
(('a', 'b'), ('u', 'v'))
問題7
如何獲得級別“2”中的值大于5的所有行? col one two b 7 4 9 5c 7 10d 6 11 8 12 8 13 6 15
query
,
df2.query("two > 5")
get_level_values
.
df2[df2.index.get_level_values('two') > 5]
注
與本例類似,我們可以使用這些構(gòu)造基于任意條件進行篩選。一般來說,記住 loc
和 xs
專門用于基于標簽的索引,而 query
和 get_level_values
有助于構(gòu)建用于過濾的通用條件掩碼。
獎金問題
如果我需要分割一個 MultiIndex
列?
np.random.seed(0)mux3 = pd.MultiIndex.from_product([ list('ABCD'), list('efgh')], names=['one','two'])df3 = pd.DataFrame(np.random.choice(10, (3, len(mux))), columns=mux3)print(df3)one A B C D two e f g h e f g h e f g h e f g h0 5 0 3 3 7 9 3 5 2 4 7 6 8 8 1 61 7 7 8 1 5 9 8 9 4 3 0 3 5 0 2 32 8 1 3 3 3 7 0 1 9 9 0 4 7 3 2 7
切成片 loc
,使用 df3.loc[:, ....] # Notice how we slice across the index with `:`.
或, df3.loc[:, pd.IndexSlice[...]]
使用 xs
在適當(dāng)?shù)那闆r下,只需傳遞一個參數(shù)。 axis=1
.可以直接訪問列級別的值。 df.columns.get_level_values
..然后你需要做一些類似的事情 df.loc[:, {condition}]
哪里 {condition}
表示使用 columns.get_level_values
.使用 query
,您的唯一選項是轉(zhuǎn)置,查詢索引,然后再次轉(zhuǎn)置: df3.T.query(...).T
不建議使用其他3種選項之一。
添加回答
舉報