从指定级别按多个值切片 MultiIndex DataFrame
Slicing a MultiIndex DataFrame by multiple values from a specified level
我想将 MultiIndex DataFrame 切片为二级的多个值。例如,在以下 DataFrame 中:
val1 val2
ind1 ind2 ind3
1 6 s1 10 8
2 7 s1 20 6
3 8 s2 30 4
4 9 s2 50 2
5 10 s3 60 0
我希望仅对 ind3 == s1
或 ind3 == s3
:
的行进行切片
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
最好的假设选项是将多个参数传递给 .xs
,因为可以明确说明所需的 level
。
我显然可以连接所有按单值切片的数据帧:
In[2]: pd.concat([df.xs('s1',level=2), df.xs('s3',level=2)])
Out[2]:
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
但是 (a) 当使用超过 2 个值时它很乏味且不那么可读,并且 (b) 对于大型数据帧它是相当重(或者至少比多值切片选项重,如果存在的话)。
下面是构建示例 DataFrame 的代码:
import pandas as pd
df = pd.DataFrame({'ind1':[1,2,3,4,5], 'ind2':[6,7,8,9,10], 'ind3':['s1','s1','s2','s2','s3'], 'val1':[10,20,30,50,60], 'val2':[8,6,4,2,0]}).set_index(['ind1','ind2','ind3'])
与 DataFrame 中的大多数选择一样,您可以使用掩码或索引器(在本例中为 loc
)。
要获取面具,您可以使用get_level_values
(docs) on the MultiIndex followed by isin
(docs)。
m = df.index.get_level_values('ind3').isin(['s1', 's3'])
df[m].reset_index(level=2, drop=True)
使用loc
:
df.loc[(slice(None), slice(None), ['s1', 's3']), :].reset_index(level=2, drop=True)
双输出
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
注意:loc
方式也可以写成 Alberto Garcia-Raboso 的回答。许多人更喜欢这种语法,因为它与 Index
的 loc
语法更一致。 the docs.
中讨论了两种语法样式
您可以使用 IndexSlice
:
idx = pd.IndexSlice
result = df.loc[idx[:, :, ['s1', 's3']], idx[:]]
result.index = result.index.droplevel('ind3')
print(result)
输出:
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
上面第二行也可以写成
result = df.loc(axis=0)[idx[:, :, ['s1', 's3']]]
我想将 MultiIndex DataFrame 切片为二级的多个值。例如,在以下 DataFrame 中:
val1 val2
ind1 ind2 ind3
1 6 s1 10 8
2 7 s1 20 6
3 8 s2 30 4
4 9 s2 50 2
5 10 s3 60 0
我希望仅对 ind3 == s1
或 ind3 == s3
:
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
最好的假设选项是将多个参数传递给 .xs
,因为可以明确说明所需的 level
。
我显然可以连接所有按单值切片的数据帧:
In[2]: pd.concat([df.xs('s1',level=2), df.xs('s3',level=2)])
Out[2]:
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
但是 (a) 当使用超过 2 个值时它很乏味且不那么可读,并且 (b) 对于大型数据帧它是相当重(或者至少比多值切片选项重,如果存在的话)。
下面是构建示例 DataFrame 的代码:
import pandas as pd
df = pd.DataFrame({'ind1':[1,2,3,4,5], 'ind2':[6,7,8,9,10], 'ind3':['s1','s1','s2','s2','s3'], 'val1':[10,20,30,50,60], 'val2':[8,6,4,2,0]}).set_index(['ind1','ind2','ind3'])
与 DataFrame 中的大多数选择一样,您可以使用掩码或索引器(在本例中为 loc
)。
要获取面具,您可以使用get_level_values
(docs) on the MultiIndex followed by isin
(docs)。
m = df.index.get_level_values('ind3').isin(['s1', 's3'])
df[m].reset_index(level=2, drop=True)
使用loc
:
df.loc[(slice(None), slice(None), ['s1', 's3']), :].reset_index(level=2, drop=True)
双输出
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
注意:loc
方式也可以写成 Alberto Garcia-Raboso 的回答。许多人更喜欢这种语法,因为它与 Index
的 loc
语法更一致。 the docs.
您可以使用 IndexSlice
:
idx = pd.IndexSlice
result = df.loc[idx[:, :, ['s1', 's3']], idx[:]]
result.index = result.index.droplevel('ind3')
print(result)
输出:
val1 val2
ind1 ind2
1 6 10 8
2 7 20 6
5 10 60 0
上面第二行也可以写成
result = df.loc(axis=0)[idx[:, :, ['s1', 's3']]]