Eu tenho um quadro de dados de vários índices com colunas 'A' e 'B'.
Existe uma maneira de selecionar linhas filtrando em uma coluna do multi-índice sem redefinir o índice para um índice de coluna única?
Por exemplo.
# 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]
python
pandas
dataframe
multi-index
silenciador
fonte
fonte
Respostas:
Uma maneira é usar o
get_level_values
método 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
No 0.13, você poderá usar
xs
com odrop_level
argumento :df.xs(1, level='A', drop_level=False) # axis=1 if columns
Observação: se fosse MultiIndex de coluna em vez de índice, você poderia usar a mesma técnica:
In [21]: df1 = df.T In [22]: df1.iloc[:, df1.columns.get_level_values('A') == 1] Out[22]: A 1 B 4 0 1
fonte
Você também pode usar o
query
que é muito legível na minha opinião e simples de usar: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
Para o que você tinha em mente, agora você pode simplesmente fazer:
df.query('A == 1') C A B 1 10 6
Você também pode ter consultas mais complexas usando
and
df.query('A >= 1 and B >= 50') C A B 3 50 8 4 80 9
e
or
df.query('A == 1 or B >= 50') C A B 1 10 6 3 50 8 4 80 9
Você também pode consultar em diferentes níveis de índice , por exemplo
df.query('A == 1 or C >= 8')
retornará
C A B 1 10 6 3 50 8 4 80 9
Se quiser usar variáveis dentro de sua consulta, você pode usar
@
:b_threshold = 20 c_threshold = 8 df.query('B >= @b_threshold and C <= @c_threshold') C A B 2 20 7 3 50 8
fonte
df.query('A == 1 or C >= 8')
df.query()
funciona bem com variáveis se elas forem referenciadas com um '@' dentro da expressão na consulta, por exemplodf.query('A == @var
) para uma variávelvar
no ambiente.Você pode usar
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
Se você deseja manter o
A
nível (odrop_level
argumento da palavra - chave só está disponível a partir da 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
fonte
Compreender como acessar o DataFrame multi-indexado do pandas pode ajudá-lo em todos os tipos de tarefas como essa.
Copie e cole no seu código para gerar o exemplo:
# 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
Dar-lhe-á uma mesa como esta:
Acesso padrão por coluna
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
Acesso por linha
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
Fatiar multi-índice
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
fonte
ValueError: cannot handle a non-unique multi-index!
erroVocê pode usar
DataFrame.loc
:>>> df.loc[1]
Exemplo
>>> 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
fonte
df.loc[0], df.loc[1]....df.loc[n]
Outra opção é:
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
fonte