Pandas MultiIndex 获取所有具有标签值的行
Pandas MultiIndex get all rows with label value
假设您有一个带有 MultiIndex 的 Panda DataFrame。您想要获取具有特定值标签的所有行。你是怎么做到的?
我的第一个想法是布尔掩码...
df[df.index.labels == 1].head()
但这不起作用。
谢谢!
您需要指定您使用的索引。在我的示例中,我采用了第二个索引(我的数据框是 s,因为它在 Pandas 的多索引页面中如此):
s[s.index.labels[1]==1]
如果您输入以下内容,您实际上可以看到索引是如何构建的:
s.index
结果结构是:
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], [1, 2]],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
names=['first', 'second'])
完整代码如下:
>>> import pandas as pd
>>> import numpy as np
>>> arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
... [1, 2, 1, 2, 1, 2, 1, 2]]
...
>>> tuples = list(zip(*arrays))
>>> index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
>>> s = pd.Series(np.random.randn(8), index=index)
>>> s[s.index.labels[1]==1]
first second
bar 2 -0.304029
baz 2 -1.216370
foo 2 1.401905
qux 2 -0.411468
dtype: float64
我会使用 xs
(cross-section):
In [11]: df = pd.DataFrame([[1, 2, 3], [3, 4, 5]], columns=list("ABC")).set_index(["A", "B"])
In [12]: df
Out[12]:
C
A B
1 2 3
3 4 5
那么你可以选择那些A级等于1的:
In [13]: df.xs(key=1, level="A")
Out[13]:
C
B
2 3
使用 drop_level=False
进行过滤(不删除 A 索引):
In [14]: df.xs(key=1, level="A", drop_level=False)
Out[14]:
C
A B
1 2 3
备选方案:
In [62]: df = pd.DataFrame({'idx1': ['A','B','C'], 'idx2':[1,2,3], 'val': [30,10,20]}).set_index(['idx1','idx2'])
In [63]: df
Out[63]:
val
idx1 idx2
A 1 30
B 2 10
C 3 20
In [64]: df[df.index.get_level_values('idx2') == 2]
Out[64]:
val
idx1 idx2
B 2 10
In [65]: df[df.index.get_level_values(1) == 2]
Out[65]:
val
idx1 idx2
B 2 10
假设您有一个带有 MultiIndex 的 Panda DataFrame。您想要获取具有特定值标签的所有行。你是怎么做到的?
我的第一个想法是布尔掩码...
df[df.index.labels == 1].head()
但这不起作用。
谢谢!
您需要指定您使用的索引。在我的示例中,我采用了第二个索引(我的数据框是 s,因为它在 Pandas 的多索引页面中如此):
s[s.index.labels[1]==1]
如果您输入以下内容,您实际上可以看到索引是如何构建的:
s.index
结果结构是:
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], [1, 2]],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
names=['first', 'second'])
完整代码如下:
>>> import pandas as pd
>>> import numpy as np
>>> arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
... [1, 2, 1, 2, 1, 2, 1, 2]]
...
>>> tuples = list(zip(*arrays))
>>> index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
>>> s = pd.Series(np.random.randn(8), index=index)
>>> s[s.index.labels[1]==1]
first second
bar 2 -0.304029
baz 2 -1.216370
foo 2 1.401905
qux 2 -0.411468
dtype: float64
我会使用 xs
(cross-section):
In [11]: df = pd.DataFrame([[1, 2, 3], [3, 4, 5]], columns=list("ABC")).set_index(["A", "B"])
In [12]: df
Out[12]:
C
A B
1 2 3
3 4 5
那么你可以选择那些A级等于1的:
In [13]: df.xs(key=1, level="A")
Out[13]:
C
B
2 3
使用 drop_level=False
进行过滤(不删除 A 索引):
In [14]: df.xs(key=1, level="A", drop_level=False)
Out[14]:
C
A B
1 2 3
备选方案:
In [62]: df = pd.DataFrame({'idx1': ['A','B','C'], 'idx2':[1,2,3], 'val': [30,10,20]}).set_index(['idx1','idx2'])
In [63]: df
Out[63]:
val
idx1 idx2
A 1 30
B 2 10
C 3 20
In [64]: df[df.index.get_level_values('idx2') == 2]
Out[64]:
val
idx1 idx2
B 2 10
In [65]: df[df.index.get_level_values(1) == 2]
Out[65]:
val
idx1 idx2
B 2 10