chọn từ gấu trúc nhiều chỉ mục


91

Tôi có một khung dữ liệu nhiều chỉ mục với các cột 'A' và 'B'.

Có cách nào để chọn hàng bằng cách lọc trên một cột của chỉ mục nhiều mà không đặt lại chỉ mục thành chỉ mục cột đơn không?

Ví dụ.

# 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]


Liên quan: Chọn các hàng trong Gấu trúc MultiIndex DataFrame (một cuộc thảo luận rộng rãi về cùng chủ đề của tôi).
cs95

Câu trả lời:


136

Một cách là sử dụng get_level_valuesphương pháp Chỉ mục:

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

Trong 0,13, bạn sẽ có thể sử dụng xsvới drop_levelđối số :

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

Lưu ý: nếu đây là cột MultiIndex thay vì chỉ mục, bạn có thể sử dụng kỹ thuật tương tự:

In [21]: df1 = df.T

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

53

Bạn cũng có thể sử dụng querymà theo ý kiến ​​của tôi là rất dễ đọc và dễ sử dụng:

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

Đối với những gì bạn đã nghĩ, bây giờ bạn có thể chỉ cần làm:

df.query('A == 1')

      C
A B    
1 10  6

Bạn cũng có thể có các truy vấn phức tạp hơn bằng cách sử dụng 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

Bạn cũng có thể truy vấn trên các mức chỉ mục khác nhau , ví dụ:

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

sẽ trở lại

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

Nếu bạn muốn sử dụng các biến bên trong truy vấn của mình, bạn có thể sử dụng@ :

b_threshold = 20
c_threshold = 8

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

      C
A B    
2 20  7
3 50  8

1
Câu trả lời tuyệt vời, cách thực sự dễ đọc hơn. Bạn có biết liệu có thể truy vấn hai trường ở cấp chỉ mục khác nhau như:df.query('A == 1 or C >= 8')
obchardon

@obchardon: Điều đó có vẻ hoạt động tốt; Tôi đã chỉnh sửa câu trả lời của mình bằng cách sử dụng ví dụ của bạn.
Cleb

1
Tôi có thời gian và chuỗi là multiindex gây ra sự cố trong biểu thức chuỗi. Tuy nhiên, df.query()chỉ hoạt động tốt với các biến nếu chúng được tham chiếu đến với '@' bên trong biểu thức trong truy vấn, ví dụ df.query('A == @var) cho một biến vartrong môi trường.
Solly

@Solly: Cảm ơn, tôi đã thêm điều này vào câu trả lời.
Cleb

Tuy nhiên, đa lập chỉ mục ở đây là ở đâu?
Lamma

32

Bạn có thể sử dụng 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

Nếu bạn muốn giữ nguyên Amức ( drop_levelđối số từ khóa chỉ có sẵn bắt đầu từ 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

1
Ha, tôi vừa cập nhật câu trả lời của mình với điều đó, Lưu ý: chỉ có sẵn trong 0,13.
Andy Hayden

Ồ, thật tốt khi biết. Tôi không bao giờ nhớ những tiện ích nhỏ nào được thêm vào trong mỗi phiên bản.
Phillip Cloud

Lol, trên thực tế câu hỏi này là một bản dupe của câu hỏi đã truyền cảm hứng cho sự tiện lợi đó! :)
Andy Hayden

13

Hiểu cách truy cập DataFrame của gấu trúc được lập chỉ mục nhiều lần có thể giúp bạn thực hiện tất cả các loại nhiệm vụ như vậy.

Sao chép, dán mã này vào mã của bạn để tạo ví dụ:

# 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

Sẽ cung cấp cho bạn bảng như thế này:

nhập mô tả hình ảnh ở đây

Truy cập tiêu chuẩn theo cột

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

Truy cập theo hàng

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

Cắt nhiều chỉ mục

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

điều này gây ra ValueError: cannot handle a non-unique multi-index!lỗi
Coddy

5

Bạn có thể sử dụng DataFrame.loc:

>>> df.loc[1]

Thí dụ

>>> 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

Đây là sản phẩm tốt nhất trong những phương pháp hiện đại IMO, nơi df.loc [2, 1] [ 'kết quả'] sẽ xử lý đa cột
Michael

điều này hoạt động với bất kỳ số nguyên nào vì một số lý do. ví dụdf.loc[0], df.loc[1]....df.loc[n]
Coddy

2

Một tùy chọn khác là:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.