Chọn hàng trong gấu trúc MultiIndex DataFrame


147

Những cách gấu trúc phổ biến nhất để chọn / lọc các hàng của khung dữ liệu có chỉ mục là MultiIndex ?

  • Cắt dựa trên một giá trị / nhãn duy nhất
  • Cắt dựa trên nhiều nhãn từ một hoặc nhiều cấp
  • Lọc các điều kiện và biểu thức boolean
  • Những phương pháp nào có thể áp dụng trong những trường hợp nào

Các giả định cho đơn giản:

  1. khung dữ liệu đầu vào không có các khóa chỉ mục trùng lặp
  2. khung dữ liệu đầu vào bên dưới chỉ có hai mức. (Hầu hết các giải pháp được hiển thị ở đây tổng quát cho N cấp độ)

Ví dụ đầu vào:

mux = pd.MultiIndex.from_arrays([
    list('aaaabbbbbccddddd'),
    list('tuvwtuvwtuvwtuvw')
], names=['one', 'two'])

df = pd.DataFrame({'col': np.arange(len(mux))}, mux)

         col
one two     
a   t      0
    u      1
    v      2
    w      3
b   t      4
    u      5
    v      6
    w      7
    t      8
c   u      9
    v     10
d   w     11
    t     12
    u     13
    v     14
    w     15

Câu hỏi 1: Chọn một mục

Làm cách nào để chọn các hàng có "a" ở cấp "một"?

         col
one two     
a   t      0
    u      1
    v      2
    w      3

Ngoài ra, làm cách nào để tôi có thể giảm mức "một" trong đầu ra?

     col
two     
t      0
u      1
v      2
w      3

Câu hỏi 1b
Làm cách nào để cắt tất cả các hàng có giá trị "t" ở mức "hai"?

         col
one two     
a   t      0
b   t      4
    t      8
d   t     12

Câu hỏi 2: Chọn nhiều giá trị trong một cấp độ

Làm cách nào tôi có thể chọn các hàng tương ứng với các mục "b" và "d" ở cấp độ "một"?

         col
one two     
b   t      4
    u      5
    v      6
    w      7
    t      8
d   w     11
    t     12
    u     13
    v     14
    w     15

Câu hỏi 2b
Làm cách nào để nhận được tất cả các giá trị tương ứng với "t" và "w" ở cấp "hai"?

         col
one two     
a   t      0
    w      3
b   t      4
    w      7
    t      8
d   w     11
    t     12
    w     15

Câu hỏi 3: Cắt một mặt cắt ngang (x, y)

Làm cách nào để truy xuất một mặt cắt ngang, tức là một hàng có giá trị cụ thể cho chỉ mục từ đó df? Cụ thể, làm thế nào để lấy lại mặt cắt ngang của ('c', 'u'), do

         col
one two     
c   u      9

Câu hỏi 4: Cắt nhiều phần chéo [(a, b), (c, d), ...]

Làm cách nào để chọn hai hàng tương ứng với ('c', 'u')('a', 'w')?

         col
one two     
c   u      9
a   w      3

Câu hỏi 5: Một mặt hàng được cắt theo cấp độ

Làm cách nào để truy xuất tất cả các hàng tương ứng với "a" ở cấp "một" hoặc "t" ở cấp "hai"?

         col
one two     
a   t      0
    u      1
    v      2
    w      3
b   t      4
    t      8
d   t     12

Câu hỏi 6: Cắt lát tùy ý

Làm cách nào để cắt các mặt cắt cụ thể? Đối với "a" và "b", tôi muốn chọn tất cả các hàng có cấp phụ "u" và "v", và đối với "d", tôi muốn chọn các hàng có cấp phụ "w".

         col
one two     
a   u      1
    v      2
b   u      5
    v      6
d   w     11
    w     15

Câu hỏi 7 sẽ sử dụng một thiết lập duy nhất bao gồm cấp số:

np.random.seed(0)
mux2 = pd.MultiIndex.from_arrays([
    list('aaaabbbbbccddddd'),
    np.random.choice(10, size=16)
], names=['one', 'two'])

df2 = pd.DataFrame({'col': np.arange(len(mux2))}, mux2)

         col
one two     
a   5      0
    0      1
    3      2
    3      3
b   7      4
    9      5
    3      6
    5      7
    2      8
c   4      9
    7     10
d   6     11
    8     12
    8     13
    1     14
    6     15

Câu hỏi 7: Lọc theo bất đẳng thức số trên các cấp độ riêng lẻ của đa chỉ mục

Làm cách nào để lấy tất cả các hàng có giá trị ở mức "hai" lớn hơn 5?

         col
one two     
b   7      4
    9      5
c   7     10
d   6     11
    8     12
    8     13
    6     15

Lưu ý: Bài đăng này sẽ không trình bày về cách tạo MultiIndexes, cách thực hiện các thao tác gán trên chúng hoặc bất kỳ cuộc thảo luận nào liên quan đến hiệu suất (đây là các chủ đề riêng biệt cho thời gian khác).

Câu trả lời:


166

MultiIndex / Advanced Indexing

Lưu ý
Bài đăng này sẽ được cấu trúc theo cách sau:

  1. Các câu hỏi được đưa ra trong OP sẽ được giải quyết, từng câu một
  2. Đối với mỗi câu hỏi, một hoặc nhiều phương pháp áp dụng để giải quyết vấn đề này và thu được kết quả mong đợi sẽ được trình bày.

Ghi chú s (giống như ghi chú này) sẽ được bao gồm cho những độc giả quan tâm đến việc tìm hiểu về chức năng bổ sung, chi tiết triển khai và thông tin khác về chủ đề hiện có. Những ghi chú này đã được biên soạn thông qua việc tìm kiếm các tài liệu và khám phá ra các tính năng khó hiểu khác nhau, và từ kinh nghiệm của riêng tôi (thừa nhận là có hạn).

Tất cả các mẫu mã đã tạo và thử nghiệm trên pandas v0.23.4, python3.7 . Nếu có điều gì đó không rõ ràng hoặc thực tế không chính xác, hoặc nếu bạn không tìm thấy giải pháp áp dụng cho trường hợp sử dụng của mình, vui lòng đề xuất chỉnh sửa, yêu cầu làm rõ trong nhận xét hoặc mở một câu hỏi mới, .... nếu có .

Đây là phần giới thiệu về một số thành ngữ phổ biến (từ đó gọi tắt là Bốn thành ngữ) chúng ta sẽ thường xuyên xem lại

  1. DataFrame.loc- Một giải pháp chung để lựa chọn theo nhãn (+ pd.IndexSlicecho các ứng dụng phức tạp hơn liên quan đến các lát cắt)

  2. DataFrame.xs - Trích xuất một phần cụ thể từ một Series / DataFrame.

  3. DataFrame.query- Chỉ định các hoạt động cắt và / hoặc lọc động (tức là, dưới dạng một biểu thức được đánh giá động. Có thể áp dụng cho một số trường hợp hơn các trường hợp khác. Cũng xem phần này của tài liệu để truy vấn trên MultiIndexes.

  4. Lập chỉ mục Boolean với một mặt nạ được tạo bằng cách sử dụng MultiIndex.get_level_values(thường kết hợp với Index.isin, đặc biệt là khi lọc với nhiều giá trị). Điều này cũng khá hữu ích trong một số trường hợp.

Sẽ rất hữu ích khi xem xét các vấn đề cắt và lọc khác nhau về Bốn thành ngữ để hiểu rõ hơn những gì có thể áp dụng cho một tình huống nhất định. Điều rất quan trọng là phải hiểu rằng không phải tất cả các thành ngữ đều hoạt động tốt như nhau (nếu có) trong mọi hoàn cảnh. Nếu một thành ngữ chưa được liệt kê như một giải pháp tiềm năng cho một vấn đề dưới đây, điều đó có nghĩa là thành ngữ đó không thể được áp dụng cho vấn đề đó một cách hiệu quả.


Câu hỏi 1

Làm cách nào để chọn các hàng có "a" ở cấp "một"?

         col
one two     
a   t      0
    u      1
    v      2
    w      3

Bạn có thể sử dụng loc, như một giải pháp mục đích chung áp dụng cho hầu hết các tình huống:

df.loc[['a']]

Tại thời điểm này, nếu bạn nhận được

TypeError: Expected tuple, got str

Điều đó có nghĩa là bạn đang sử dụng phiên bản gấu trúc cũ hơn. Cân nhắc nâng cấp! Nếu không, hãy sử dụng df.loc[('a', slice(None)), :].

Ngoài ra, bạn có thể sử dụng xsở đây, vì chúng tôi đang trích xuất một mặt cắt ngang. Lưu ý các đối số levelsaxis(các giá trị mặc định hợp lý có thể được giả định ở đây).

df.xs('a', level=0, axis=0, drop_level=False)
# df.xs('a', drop_level=False)

Ở đây, drop_level=Falseđối số là cần thiết để ngăn chặn việc xsgiảm cấp độ "một" trong kết quả (cấp độ chúng tôi đã phân tích).

Tuy nhiên, một tùy chọn khác ở đây đang sử dụng query:

df.query("one == 'a'")

Nếu chỉ mục không có tên, bạn sẽ cần thay đổi chuỗi truy vấn của mình thành "ilevel_0 == 'a'".

Cuối cùng, sử dụng 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']

Ngoài ra, làm cách nào để tôi có thể giảm mức "một" trong đầu ra?

     col
two     
t      0
u      1
v      2
w      3

Điều này có thể dễ dàng thực hiện bằng cách sử dụng

df.loc['a'] # Notice the single string argument instead the list.

Hoặc là,

df.xs('a', level=0, axis=0, drop_level=True)
# df.xs('a')

Lưu ý rằng chúng ta có thể bỏ qua drop_levelđối số (nó được giả định là Truetheo mặc định).

Lưu ý
Bạn có thể nhận thấy rằng một DataFrame đã lọc vẫn có thể có tất cả các cấp, ngay cả khi chúng không hiển thị khi in DataFrame ra. Ví dụ,

v = df.loc[['a']]
print(v)
         col
one two     
a   t      0
    u      1
    v      2
    w      3

print(v.index)
MultiIndex(levels=[['a', 'b', 'c', 'd'], ['t', 'u', 'v', 'w']],
           labels=[[0, 0, 0, 0], [0, 1, 2, 3]],
           names=['one', 'two'])

Bạn có thể thoát khỏi các cấp độ này bằng cách sử dụng 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'])

Câu hỏi 1b

Làm cách nào để cắt tất cả các hàng có giá trị "t" trên cấp "hai"?

         col
one two     
a   t      0
b   t      4
    t      8
d   t     12

Theo trực giác, bạn sẽ muốn điều gì đó liên quan đến slice():

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

Nó chỉ hoạt động! ™ Nhưng nó rất khó. Chúng tôi có thể hỗ trợ cú pháp cắt tự nhiên hơn bằng cách sử dụng pd.IndexSliceAPI tại đây.

idx = pd.IndexSlice
df.loc[idx[:, 't'], :]

Cái này sạch hơn nhiều.

Lưu ý
Tại sao cần có lát cắt theo sau :trên các cột? Điều này là do, loccó thể được sử dụng để chọn và cắt dọc theo cả hai trục ( axis=0hoặc axis=1). Nếu không nói rõ việc cắt lát sẽ được thực hiện trên trục nào, hoạt động sẽ trở nên mơ hồ. Xem hộp lớn màu đỏ trong tài liệu về cách cắt .

Nếu bạn muốn loại bỏ bất kỳ bóng mờ nào, hãy locchấp nhận một axis tham số:

df.loc(axis=0)[pd.IndexSlice[:, 't']]

Nếu không có axistham số (tức là chỉ bằng cách thực hiện df.loc[pd.IndexSlice[:, 't']]), việc cắt lát được giả định là trên các cột và a KeyErrorsẽ được nâng lên trong trường hợp này.

Điều này được ghi lại trong máy thái . Tuy nhiên, đối với mục đích của bài đăng này, chúng tôi sẽ chỉ định rõ ràng tất cả các trục.

Với xs, nó là

df.xs('t', axis=0, level=1, drop_level=False)

Với query, nó là

df.query("two == 't'")
# Or, if the first level has no name, 
# df.query("ilevel_1 == 't'") 

Và cuối cùng, với get_level_values, bạn có thể làm

df[df.index.get_level_values('two') == 't']
# Or, to perform selection by position/integer,
# df[df.index.get_level_values(1) == 't']

Tất cả đều có cùng một hiệu quả.


Câu hỏi 2

Làm cách nào tôi có thể chọn các hàng tương ứng với các mục "b" và "d" ở cấp độ "một"?

         col
one two     
b   t      4
    u      5
    v      6
    w      7
    t      8
d   w     11
    t     12
    u     13
    v     14
    w     15

Sử dụng loc, điều này được thực hiện theo cách tương tự bằng cách chỉ định một danh sách.

df.loc[['b', 'd']]

Để giải quyết vấn đề ở trên khi chọn "b" và "d", bạn cũng có thể sử dụng 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')

Lưu ý
Có, trình phân tích cú pháp mặc định là 'pandas', nhưng điều quan trọng là phải làm nổi bật cú pháp này không phải là python thông thường. Bộ phân tích cú pháp Pandas tạo ra một cây phân tích cú pháp hơi khác với biểu thức. Điều này được thực hiện để làm cho một số hoạt động trực quan hơn để chỉ định. Để biết thêm thông tin, vui lòng đọc bài đăng của tôi về Đánh giá biểu hiện động ở gấu trúc bằng cách sử dụng pd.eval () .

Và, với get_level_values+ Index.isin:

df[df.index.get_level_values("one").isin(['b', 'd'])]

Câu hỏi 2b

Làm cách nào để nhận tất cả các giá trị tương ứng với "t" và "w" ở cấp "hai"?

         col
one two     
a   t      0
    w      3
b   t      4
    w      7
    t      8
d   w     11
    t     12
    w     15

Với loc, điều này chỉ có thể xảy ra với pd.IndexSlice.

df.loc[pd.IndexSlice[:, ['t', 'w']], :] 

Ruột kết đầu tiên :trong pd.IndexSlice[:, ['t', 'w']]phương tiện để cắt trên cấp độ đầu tiên. Khi độ sâu của cấp độ đang được truy vấn tăng lên, bạn sẽ cần chỉ định nhiều lát cắt hơn, một lát cắt trên mỗi cấp độ. Tuy nhiên, bạn sẽ không cần chỉ định thêm các cấp ngoài mức đang được cắt.

Với query, đây là

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

Với get_level_valuesIndex.isin(tương tự như trên):

df[df.index.get_level_values('two').isin(['t', 'w'])]

Câu hỏi 3

Làm cách nào để truy xuất một mặt cắt ngang, tức là một hàng có giá trị cụ thể cho chỉ mục từ đó df? Cụ thể, làm thế nào để lấy lại mặt cắt ngang của ('c', 'u'), do

         col
one two     
c   u      9

Sử dụng locbằng cách chỉ định một bộ khóa:

df.loc[('c', 'u'), :]

Hoặc là,

df.loc[pd.IndexSlice[('c', 'u')]]

Lưu ý
Tại thời điểm này, bạn có thể gặp phải một PerformanceWarningcái nhìn như thế này:

PerformanceWarning: indexing past lexsort depth may impact performance.

Điều này chỉ có nghĩa là chỉ mục của bạn không được sắp xếp. pandas phụ thuộc vào chỉ mục được sắp xếp (trong trường hợp này, về mặt từ vựng, vì chúng tôi đang xử lý các giá trị chuỗi) để tìm kiếm và truy xuất tối ưu. Một cách khắc phục nhanh chóng là sắp xếp DataFrame của bạn trước bằng cách sử dụng DataFrame.sort_index. Điều này đặc biệt mong muốn từ quan điểm hiệu suất nếu bạn có kế hoạch thực hiện song song nhiều truy vấn như vậy:

df_sort = df.sort_index()
df_sort.loc[('c', 'u')]

Bạn cũng có thể sử dụng MultiIndex.is_lexsorted()để kiểm tra xem chỉ mục có được sắp xếp hay không. Hàm này trả về Truehoặc Falsetương ứng. Bạn có thể gọi hàm này để xác định xem có cần thêm một bước sắp xếp hay không.

Với xs, điều này lại chỉ đơn giản là chuyển một bộ giá trị duy nhất làm đối số đầu tiên, với tất cả các đối số khác được đặt thành giá trị mặc định thích hợp của chúng:

df.xs(('c', 'u'))

Với query, mọi thứ trở nên hơi rắc rối:

df.query("one == 'c' and two == 'u'")

Bạn có thể thấy rằng điều này sẽ tương đối khó để khái quát hóa. Nhưng vẫn ổn cho vấn đề cụ thể này.

Với quyền truy cập trải dài nhiều cấp, get_level_valuesvẫn có thể được sử dụng, nhưng không được khuyến khích:

m1 = (df.index.get_level_values('one') == 'c')
m2 = (df.index.get_level_values('two') == 'u')
df[m1 & m2]

Câu hỏi 4

Làm cách nào để chọn hai hàng tương ứng với ('c', 'u')('a', 'w')?

         col
one two     
c   u      9
a   w      3

Với loc, điều này vẫn đơn giản như:

df.loc[[('c', 'u'), ('a', 'w')]]
# df.loc[pd.IndexSlice[[('c', 'u'), ('a', 'w')]]]

Với query, bạn sẽ cần tạo động một chuỗi truy vấn bằng cách lặp qua các phần và cấp của mình:

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)

100% KHÔNG KHUYẾN CÁO! Nhưng nó hoàn toàn có thể.


Câu hỏi 5

Làm cách nào để truy xuất tất cả các hàng tương ứng với "a" ở cấp "một" hoặc "t" ở cấp "hai"?

         col
one two     
a   t      0
    u      1
    v      2
    w      3
b   t      4
    t      8
d   t     12

Điều này thực sự rất khó thực hiện loctrong khi vẫn đảm bảo tính đúng đắn vẫn duy trì sự rõ ràng của mã. df.loc[pd.IndexSlice['a', 't']]là không chính xác, nó được hiểu là df.loc[pd.IndexSlice[('a', 't')]](tức là chọn một mặt cắt ngang). Bạn có thể nghĩ đến một giải pháp pd.concatđể xử lý từng nhãn riêng biệt:

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      8
d   t     12

Nhưng bạn sẽ nhận thấy một trong các hàng bị trùng lặp. Điều này là do hàng đó thỏa mãn cả hai điều kiện cắt và do đó xuất hiện hai lần. Thay vào đó bạn sẽ cần phải làm

v = pd.concat([
        df.loc[['a'],:], df.loc[pd.IndexSlice[:, 't'],:]
])
v[~v.index.duplicated()]

Nhưng nếu DataFrame của bạn vốn có chứa các chỉ số trùng lặp (mà bạn muốn), thì điều này sẽ không giữ lại chúng. Sử dụng hết sức thận trọng .

Với query, điều này thật đơn giản:

df.query("one == 'a' or two == 't'")

Với get_level_values, điều này vẫn đơn giản, nhưng không thanh lịch:

m1 = (df.index.get_level_values('one') == 'a')
m2 = (df.index.get_level_values('two') == 't')
df[m1 | m2] 

Câu hỏi 6

Làm cách nào để cắt các mặt cắt cụ thể? Đối với "a" và "b", tôi muốn chọn tất cả các hàng có cấp phụ "u" và "v", và đối với "d", tôi muốn chọn các hàng có cấp phụ "w".

         col
one two     
a   u      1
    v      2
b   u      5
    v      6
d   w     11
    w     15

Đây là một trường hợp đặc biệt mà tôi đã thêm vào để giúp hiểu khả năng áp dụng của Bốn thành ngữ — đây là một trường hợp mà không có thành ngữ nào hoạt động hiệu quả, vì cách cắt rất cụ thể và không tuân theo bất kỳ hình mẫu thực tế nào.

Thông thường, các vấn đề cắt như thế này sẽ yêu cầu chuyển một cách rõ ràng danh sách các khóa đến loc. Một cách để làm điều này là với:

keys = [('a', 'u'), ('a', 'v'), ('b', 'u'), ('b', 'v'), ('d', 'w')]
df.loc[keys, :]

Nếu bạn muốn lưu một số thao tác nhập, bạn sẽ nhận ra rằng có một mẫu để cắt "a", "b" và các cấp lại của nó, vì vậy chúng ta có thể tách tác vụ cắt thành hai phần và concatkết quả:

pd.concat([
     df.loc[(('a', 'b'), ('u', 'v')), :], 
     df.loc[('d', 'w'), :]
   ], axis=0)

Đặc điểm kỹ thuật cắt lát cho "a" và "b" rõ ràng hơn một chút (('a', 'b'), ('u', 'v'))vì các cấp con giống nhau được lập chỉ mục giống nhau cho mỗi cấp.


Câu hỏi 7

Làm cách nào để lấy tất cả các hàng có giá trị ở mức "hai" lớn hơn 5?

         col
one two     
b   7      4
    9      5
c   7     10
d   6     11
    8     12
    8     13
    6     15

Điều này có thể được thực hiện bằng cách sử dụng query,

df2.query("two > 5")

get_level_values.

df2[df2.index.get_level_values('two') > 5]

Lưu ý
Tương tự như ví dụ này, chúng ta có thể lọc dựa trên bất kỳ điều kiện tùy ý nào bằng cách sử dụng các cấu trúc này. Nói chung, sẽ rất hữu ích khi ghi nhớ điều đó locxsdành riêng cho việc lập chỉ mục dựa trên nhãn, trong khi queryget_level_valuesrất hữu ích cho việc xây dựng các mặt nạ có điều kiện chung để lọc.


Câu hỏi thưởng

Điều gì sẽ xảy ra nếu tôi cần cắt một MultiIndex cột ?

Trên thực tế, hầu hết các giải pháp ở đây cũng có thể áp dụng cho các cột, với những thay đổi nhỏ. Xem xét:

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  h
0    5  0  3  3  7  9  3  5  2  4  7  6  8  8  1  6
1    7  7  8  1  5  9  8  9  4  3  0  3  5  0  2  3
2    8  1  3  3  3  7  0  1  9  9  0  4  7  3  2  7

Đây là những thay đổi sau đây bạn sẽ cần thực hiện đối với Bốn thành ngữ để chúng hoạt động với các cột.

  1. Để cắt lát loc, hãy sử dụng

    df3.loc[:, ....] # Notice how we slice across the index with `:`. 

    hoặc là,

    df3.loc[:, pd.IndexSlice[...]]
  2. Để sử dụng xskhi thích hợp, chỉ cần chuyển một đối số axis=1.

  3. Bạn có thể truy cập trực tiếp các giá trị cấp cột bằng cách sử dụng df.columns.get_level_values. Sau đó, bạn sẽ cần phải làm một cái gì đó như

    df.loc[:, {condition}] 

    Nơi {condition}đại diện cho một số điều kiện được xây dựng bằng cách sử dụng columns.get_level_values.

  4. Để sử dụng query, tùy chọn duy nhất của bạn là chuyển vị, truy vấn trên chỉ mục và chuyển vị lại:

    df3.T.query(...).T

    Không khuyến khích, sử dụng một trong 3 tùy chọn còn lại.


6

Gần đây, tôi đã gặp một trường hợp sử dụng trong đó tôi có khung dữ liệu đa chỉ mục cấp 3+ mà trong đó tôi không thể thực hiện bất kỳ giải pháp nào ở trên tạo ra kết quả mà tôi đang tìm kiếm. Rất có thể các giải pháp trên tất nhiên phù hợp với trường hợp sử dụng của tôi và tôi đã thử một số giải pháp, tuy nhiên tôi không thể làm cho chúng hoạt động với thời gian tôi có.

Tôi không phải là chuyên gia, nhưng tôi tình cờ gặp một giải pháp không được liệt kê trong các câu trả lời toàn diện ở trên. Tôi không đảm bảo rằng các giải pháp là tối ưu theo bất kỳ cách nào.

Đây là một cách khác để có kết quả hơi khác với Câu hỏi số 6 ở trên. (và có thể là các câu hỏi khác)

Cụ thể tôi đang tìm kiếm:

  1. Một cách để chọn hai + giá trị từ một cấp của chỉ mục và một giá trị từ cấp khác của chỉ mục và
  2. Một cách để để lại các giá trị chỉ mục từ thao tác trước đó trong đầu ra khung dữ liệu.

Như một cờ lê khỉ trong bánh răng (tuy nhiên hoàn toàn có thể sửa được):

  1. Các chỉ mục không được đặt tên.

Trên khung dữ liệu đồ chơi bên dưới:

    index = pd.MultiIndex.from_product([['a','b'],
                               ['stock1','stock2','stock3'],
                               ['price','volume','velocity']])

    df = pd.DataFrame([1,2,3,4,5,6,7,8,9,
                      10,11,12,13,14,15,16,17,18], 
                       index)

                        0
    a stock1 price      1
             volume     2
             velocity   3
      stock2 price      4
             volume     5
             velocity   6
      stock3 price      7
             volume     8
             velocity   9
    b stock1 price     10
             volume    11
             velocity  12
      stock2 price     13
             volume    14
             velocity  15
      stock3 price     16
             volume    17
             velocity  18

Tất nhiên, bằng cách sử dụng các công cụ dưới đây:

    df.xs(('stock1', 'velocity'), level=(1,2))

        0
    a   3
    b  12

Nhưng tôi muốn một kết quả khác, vì vậy phương pháp của tôi để có được kết quả đó là:

   df.iloc[df.index.isin(['stock1'], level=1) & 
           df.index.isin(['velocity'], level=2)] 

                        0
    a stock1 velocity   3
    b stock1 velocity  12

Và nếu tôi muốn hai + giá trị từ một cấp và một giá trị (hoặc 2+) từ cấp khác:

    df.iloc[df.index.isin(['stock1','stock3'], level=1) & 
            df.index.isin(['velocity'], level=2)] 

                        0
    a stock1 velocity   3
      stock3 velocity   9
    b stock1 velocity  12
      stock3 velocity  18

Phương pháp trên có lẽ hơi rắc rối, tuy nhiên tôi thấy nó đáp ứng được nhu cầu của tôi và như một phần thưởng là tôi dễ hiểu và dễ đọc hơn.


2
Tốt đẹp, không biết về levelđối số Index.isin!
cs95
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.