2013-08-27 3 views
11

У меня есть DataFrame с колоннами мультииндексными, который выглядит следующим образом:Как выбрать только определенные столбцы из DataFrame с столбцами 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

Что такое правильный, простой способ выбора только определенные столбцы (например, ['a', 'c'], а не диапазон) от второго уровня?

В настоящее время я делаю это так:

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

Он не чувствует, как хорошее решение, однако, потому что я должен вспыхнуть itertools, построить еще один мультииндексных вручную и затем reindex (и мой фактический код еще более беспорядочен, так как списки столбцов не так просто получить). Я уверен, что должен быть какой-то ix или xs способ сделать это, но все, что я пробовал, вызвало ошибки.

+0

Вы пробовали использовать словари? – darmat

+0

Нет, не знаю. Вы хотите быстрее построить MultiIndex? Если это так, это не главное - я бы хотел его избежать и проиндексировать непосредственно с чем-то вроде data.xs (['a', 'c'], axis = 1, level = 1) ' – metakermit

+0

предположим следующее: – darmat

ответ

6

Это не большой, но, может быть:

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

будет работать?

+0

На самом деле я думаю, что это оптимальный способ фильтрации списка меток на произвольном уровне MultiIndex без создания всех кортежей. Я просто использовал 'loc' для ясности. –

+0

Чтобы сохранить порядок столбцов, лучше использовать 'isin ([" a "," b "])'. – Peaceful

+0

@Peaceful: что? Это ничего не меняет. Результатом вызова isin является серия bool, и его порядок определяется порядком исходной серии, а не аргументом isin. – DSM

8

Вы можете использовать либо, loc или ix я покажу пример с loc:

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

Если у вас есть мультииндексированные DataFrame, и вы хотите, чтобы отфильтровать только некоторые из столбцов, вы должны передайте список кортежей, соответствующих этим столбцам. Таким образом, itertools подход был в значительной степени хорошо, но вы не должны создать новый мультииндексных:

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

Спасибо, это тоже хорошее решение! – metakermit

13

Я думаю, что есть гораздо лучше (сейчас), поэтому я утруждать вытягивать этот вопрос (который был лучшим результатом Google) из тени:

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

дает ваш ожидаемый результат в быстрый и чистый один вкладыш:

 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 

это в основном самостоятельно объяснить, то [1] относится к уровню.

4

Чтобы выбрать все столбцы с именами 'a' и 'c' на втором уровне вашей колонки индексатор, вы можете использовать ломтерезки:

>>> 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 вы можете прочитать больше о ломтерезки.

Смежные вопросы