从多指标的大熊猫中选择

我有一个多索引数据框架,列‘ A’和‘ B’。

有没有一种方法可以通过对多索引中的一列进行过滤而不将索引重置为单列索引来选择行?

例如。

# has multi-index (A,B)
df
#can I do this? I know this doesn't work because the index is multi-index so I need to     specify a tuple


df.ix[df.A ==1]
203823 次浏览

一种方法是使用 get_level_values Index 方法:

In [11]: df
Out[11]:
0
A B
1 4  1
2 5  2
3 6  3


In [12]: df.iloc[df.index.get_level_values('A') == 1]
Out[12]:
0
A B
1 4  1

在0.13中你可以使用 带 ABC1参数的 xs:

df.xs(1, level='A', drop_level=False) # axis=1 if columns

注意: 如果这是 MultiIndex 列而不是 index,您可以使用相同的技术:

In [21]: df1 = df.T


In [22]: df1.iloc[:, df1.columns.get_level_values('A') == 1]
Out[22]:
A  1
B  4
0  1

你可以使用 DataFrame.xs():

In [36]: df = DataFrame(np.random.randn(10, 4))


In [37]: df.columns = [np.random.choice(['a', 'b'], size=4).tolist(), np.random.choice(['c', 'd'], size=4)]


In [38]: df.columns.names = ['A', 'B']


In [39]: df
Out[39]:
A      b             a
B      d      d      d      d
0 -1.406  0.548 -0.635  0.576
1 -0.212 -0.583  1.012 -1.377
2  0.951 -0.349 -0.477 -1.230
3  0.451 -0.168  0.949  0.545
4 -0.362 -0.855  1.676 -2.881
5  1.283  1.027  0.085 -1.282
6  0.583 -1.406  0.327 -0.146
7 -0.518 -0.480  0.139  0.851
8 -0.030 -0.630 -1.534  0.534
9  0.246 -1.558 -1.885 -1.543


In [40]: df.xs('a', level='A', axis=1)
Out[40]:
B      d      d
0 -0.635  0.576
1  1.012 -1.377
2 -0.477 -1.230
3  0.949  0.545
4  1.676 -2.881
5  0.085 -1.282
6  0.327 -0.146
7  0.139  0.851
8 -1.534  0.534
9 -1.885 -1.543

如果希望保持 A级别(drop_level关键字参数仅从 v0.13.0开始可用) :

In [42]: df.xs('a', level='A', axis=1, drop_level=False)
Out[42]:
A      a
B      d      d
0 -0.635  0.576
1  1.012 -1.377
2 -0.477 -1.230
3  0.949  0.545
4  1.676 -2.881
5  0.085 -1.282
6  0.327 -0.146
7  0.139  0.851
8 -1.534  0.534
9 -1.885 -1.543

你也可以使用 query,我认为它非常易读,而且使用起来很简单:

import pandas as pd


df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [10, 20, 50, 80], 'C': [6, 7, 8, 9]})
df = df.set_index(['A', 'B'])


C
A B
1 10  6
2 20  7
3 50  8
4 80  9

对于你心中所想的,你现在可以简单地做:

df.query('A == 1')


C
A B
1 10  6

还可以使用 and进行更复杂的查询

df.query('A >= 1 and B >= 50')


C
A B
3 50  8
4 80  9

or

df.query('A == 1 or B >= 50')


C
A B
1 10  6
3 50  8
4 80  9

你亦可选择 不同索引级别的查询,例如。

df.query('A == 1 or C >= 8')

会回来的

      C
A B
1 10  6
3 50  8
4 80  9

如果您想在查询中使用变量,你可以使用 @:

b_threshold = 20
c_threshold = 8


df.query('B >= @b_threshold and C <= @c_threshold')


C
A B
2 20  7
3 50  8

你可以使用 DataFrame.loc:

>>> df.loc[1]

例子

>>> print(df)
result
A B C
1 1 1       6
2       9
2 1       8
2      11
2 1 1       7
2      10
2 1       9
2      12


>>> print(df.loc[1])
result
B C
1 1       6
2       9
2 1       8
2      11


>>> print(df.loc[2, 1])
result
C
1       7
2      10

另一个选择是:

filter1 = df.index.get_level_values('A') == 1
filter2 = df.index.get_level_values('B') == 4


df.iloc[filter1 & filter2]
Out[11]:
0
A B
1 4  1

理解 如何访问多索引熊猫数据框架可以帮助您完成各种类似的任务。

将此复制粘贴到代码中以生成示例:

# hierarchical indices and columns
index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]],
names=['year', 'visit'])
columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']],
names=['subject', 'type'])


# mock some data
data = np.round(np.random.randn(4, 6), 1)
data[:, ::2] *= 10
data += 37


# create the DataFrame
health_data = pd.DataFrame(data, index=index, columns=columns)
health_data

会给你这样的桌子:

enter image description here

按列标准访问

health_data['Bob']
type       HR   Temp
year visit
2013    1   22.0    38.6
2   52.0    38.3
2014    1   30.0    38.9
2   31.0    37.3




health_data['Bob']['HR']
year  visit
2013  1        22.0
2        52.0
2014  1        30.0
2        31.0
Name: HR, dtype: float64


# filtering by column/subcolumn - your case:
health_data['Bob']['HR']==22
year  visit
2013  1         True
2        False
2014  1        False
2        False


health_data['Bob']['HR'][2013]
visit
1    22.0
2    52.0
Name: HR, dtype: float64


health_data['Bob']['HR'][2013][1]
22.0

按行访问

health_data.loc[2013]
subject Bob Guido   Sue
type    HR  Temp    HR  Temp    HR  Temp
visit
1   22.0    38.6    40.0    38.9    53.0    37.5
2   52.0    38.3    42.0    34.6    30.0    37.7


health_data.loc[2013,1]
subject  type
Bob      HR      22.0
Temp    38.6
Guido    HR      40.0
Temp    38.9
Sue      HR      53.0
Temp    37.5
Name: (2013, 1), dtype: float64


health_data.loc[2013,1]['Bob']
type
HR      22.0
Temp    38.6
Name: (2013, 1), dtype: float64


health_data.loc[2013,1]['Bob']['HR']
22.0

多索引切片

idx=pd.IndexSlice
health_data.loc[idx[:,1], idx[:,'HR']]
subject Bob Guido   Sue
type    HR  HR  HR
year    visit
2013    1   22.0    40.0    53.0
2014    1   30.0    52.0    45.0

你可以使用 MultiIndex切片,例如:

arrays = [["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
["one", "two", "one", "two", "one", "two", "one", "two"]]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=["A", "B"])
df = pd.DataFrame(np.random.randint(9, size=(8, 2)), index=index, columns=["col1", "col2"])


col1  col2
A   B
bar one     0     8
two     4     8
baz one     6     0
two     7     3
foo one     6     8
two     2     6
qux one     7     0
two     6     4

AtwoB中选择所有内容:

df.loc[(slice(None), 'two'), :]

产出:

         col1  col2
A   B
bar two     4     8
baz two     7     3
foo two     2     6
qux two     6     4

A中选择 barbaz,从 B中选择 two:

df.loc[(['bar', 'baz'], 'two'), :]

产出:

         col1  col2
A   B
bar two     4     8
baz two     7     3