2013-08-27 35 views
11

Tôi có DataFrame với các cột MultiIndex trông như thế này:Làm cách nào để chỉ chọn các cột cụ thể từ một DataFrame với các cột MultiIndex?

# sample data 
col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'], 
           ['a', 'b', 'c', 'a', 'b', 'c']]) 
data = pd.DataFrame(np.random.randn(4, 6), columns=col) 
data 

sample data

những cách đơn giản, thích hợp của việc lựa chọn chỉ các cột cụ thể (ví dụ ['a', 'c'], không phải là một range) từ cấp độ thứ hai là gì?

Hiện nay tôi đang làm việc đó như thế này:

import itertools 
tuples = [i for i in itertools.product(['one', 'two'], ['a', 'c'])] 
new_index = pd.MultiIndex.from_tuples(tuples) 
print(new_index) 
data.reindex_axis(new_index, axis=1) 

expected result

Nó không cảm thấy giống như một giải pháp tốt, tuy nhiên, vì tôi phải bust ra itertools, xây dựng khác MultiIndex bằng tay và sau đó reindex (và mã thực sự của tôi thậm chí còn lộn xộn hơn, vì các danh sách cột không đơn giản để tìm nạp). Tôi khá chắc chắn phải có một số cách ix hoặc xs cách thực hiện việc này, nhưng mọi thứ tôi đã thử đều dẫn đến lỗi.

+0

Bạn đã thử sử dụng từ điển chưa? – darmat

+0

Không, tôi chưa có. Bạn có nghĩa là để nhanh chóng xây dựng MultiIndex? Nếu vậy, đó không phải là vấn đề - tôi muốn tránh nó và chỉ mục trực tiếp với một cái gì đó như 'data.xs (['a', 'c'], axis = 1, level = 1)' – metakermit

+0

giả sử điều này: – darmat

Trả lời

6

Đó không phải là lớn, nhưng có lẽ:

>>> data 
     one       two      
      a   b   c   a   b   c 
0 -0.927134 -1.204302 0.711426 0.854065 -0.608661 1.140052 
1 -0.690745 0.517359 -0.631856 0.178464 -0.312543 -0.418541 
2 1.086432 0.194193 0.808235 -0.418109 1.055057 1.886883 
3 -0.373822 -0.012812 1.329105 1.774723 -2.229428 -0.617690 
>>> data.ix[:,data.columns.get_level_values(1).isin({"a", "c"})] 
     one     two   
      a   c   a   c 
0 -0.927134 0.711426 0.854065 1.140052 
1 -0.690745 -0.631856 0.178464 -0.418541 
2 1.086432 0.808235 -0.418109 1.886883 
3 -0.373822 1.329105 1.774723 -0.617690 

sẽ làm việc?

+0

Thực ra tôi nghĩ đây là cách tối ưu để lọc ra một danh sách các nhãn ở mức độ tùy ý của MultiIndex mà không cần tạo tất cả các bộ dữ liệu. Tôi sẽ chỉ sử dụng 'loc' để làm rõ. –

+0

Để duy trì thứ tự các cột, tốt hơn là sử dụng 'isin ([" a "," b "])'. – Peaceful

+0

@Peaceful: cái gì? Điều đó không thay đổi bất cứ điều gì. Kết quả của cuộc gọi isin là một bool Series, và thứ tự của nó được xác định theo thứ tự của Series gốc, không phải là đối số của isin. – DSM

8

Bạn có thể sử dụng một trong hai, hoặc locix tôi sẽ hiển thị một ví dụ với loc:

data.loc[:, [('one', 'a'), ('one', 'c'), ('two', 'a'), ('two', 'c')]] 

Khi bạn có một MultiIndexed DataFrame, và bạn muốn lọc ra chỉ một số các cột, bạn phải chuyển danh sách các bộ dữ liệu phù hợp với các cột đó. Vì vậy, cách tiếp cận itertools đã được khá nhiều OK, nhưng bạn không cần phải tạo ra một MultiIndex mới:

data.loc[:, list(itertools.product(['one', 'two'], ['a', 'c']))] 
+0

Cảm ơn, đó cũng là một giải pháp tốt! – metakermit

13

Tôi nghĩ rằng có một cách tốt hơn nhiều (bây giờ), đó là lý do tôi bận tâm kéo câu hỏi này (đó là kết quả google trên cùng) ra khỏi bóng tối:

data.select(lambda x: x[1] in ['a', 'b'], axis=1) 

mang lại kết quả mong muốn của bạn trong một nhanh chóng và sạch sẽ một lớp lót:

 one     two   
      a   b   a   b 
0 -0.341326 0.374504 0.534559 0.429019 
1 0.272518 0.116542 -0.085850 -0.330562 
2 1.982431 -0.420668 -0.444052 1.049747 
3 0.162984 -0.898307 1.762208 -0.101360 

Chủ yếu là tự giải thích, [1] là mức.

4

Để chọn tất cả các cột được đặt tên 'a''c' ở cấp thứ hai của indexer cột, bạn có thể sử dụng máy thái:

>>> data.loc[:, (slice(None), ('a', 'c'))] 

     one     two   
      a   c   a   c 
0 -0.983172 -2.495022 -0.967064 0.124740 
1 0.282661 -0.729463 -0.864767 1.716009 
2 0.942445 1.276769 -0.595756 -0.973924 
3 2.182908 -0.267660 0.281916 -0.587835 

Here bạn có thể đọc thêm về Slicer.

Các vấn đề liên quan