Eu tenho uma série como esta depois de fazer groupby ('nome') e usar a função mean () em outra coluna
name
383 3.000000
663 1.000000
726 1.000000
737 9.000000
833 8.166667
Alguém poderia me mostrar como filtrar as linhas com valores médios de 1.000000? Obrigado e agradeço muito sua ajuda.
Respostas:
In [5]: import pandas as pd test = { 383: 3.000000, 663: 1.000000, 726: 1.000000, 737: 9.000000, 833: 8.166667 } s = pd.Series(test) s = s[s != 1] s Out[0]: 383 3.000000 737 9.000000 833 8.166667 dtype: float64
fonte
s
e depois usar duas vezes na expressão). Porém, só funciona com pandas 0.18.A partir do pandas versão 0.18+, a filtragem de uma série também pode ser feita como abaixo
test = { 383: 3.000000, 663: 1.000000, 726: 1.000000, 737: 9.000000, 833: 8.166667 } pd.Series(test).where(lambda x : x!=1).dropna()
Checkout: http://pandas.pydata.org/pandas-docs/version/0.18.1/whatsnew.html#method-chaininng-improvements
fonte
Como o DACW apontou , há melhorias no encadeamento de métodos no pandas 0.18.1 que fazem o que você está procurando muito bem.
Em vez de usar
.where
, você pode passar sua função para o.loc
indexador ou para o indexador Series[]
e evitar a chamada para.dropna
:test = pd.Series({ 383: 3.000000, 663: 1.000000, 726: 1.000000, 737: 9.000000, 833: 8.166667 }) test.loc[lambda x : x!=1] test[lambda x: x!=1]
Comportamento semelhante é suportado nas classes DataFrame e NDFrame.
fonte
Uma maneira rápida de fazer isso é reconstruir usando
numpy
para fatiar os arrays subjacentes. Veja os horários abaixo.mask = s.values != 1 pd.Series(s.values[mask], s.index[mask]) 0 383 3.000000 737 9.000000 833 8.166667 dtype: float64
tempo ingênuo
fonte
Outra maneira é primeiro converter para um DataFrame e usar o método de consulta (supondo que você tenha numexpr instalado):
import pandas as pd test = { 383: 3.000000, 663: 1.000000, 726: 1.000000, 737: 9.000000, 833: 8.166667 } s = pd.Series(test) s.to_frame(name='x').query("x != 1")
fonte
Se você gosta de uma operação em cadeia, também pode usar a
compress
função:test = pd.Series({ 383: 3.000000, 663: 1.000000, 726: 1.000000, 737: 9.000000, 833: 8.166667 }) test.compress(lambda x: x != 1) # 383 3.000000 # 737 9.000000 # 833 8.166667 # dtype: float64
fonte
No meu caso, tive uma série de panda onde os valores são tuplas de caracteres :
Out[67] 0 (H, H, H, H) 1 (H, H, H, T) 2 (H, H, T, H) 3 (H, H, T, T) 4 (H, T, H, H)
Portanto, eu poderia usar a indexação para filtrar a série, mas para criar o índice de que precisava
apply
. Minha condição é "encontre todas as tuplas que têm exatamente um 'H'".series_of_tuples[series_of_tuples.apply(lambda x: x.count('H')==1)]
Eu admito que não é "encadeado" , (isto é, repito
series_of_tuples
duas vezes; você deve armazenar qualquer série temporária em uma variável para que possa chamar apply (...) nela).Também pode haver outros métodos (além
.apply(...)
) que podem operar elemento a elemento para produzir um índice booleano.Muitas outras respostas (incluindo resposta aceita) usando as funções encadeadas como:
.compress()
.where()
.loc[]
[]
Eles aceitam chamáveis (lambdas) que são aplicados à Série , não aos valores individuais dessas séries!
Portanto, minha série de tuplas se comportou de forma estranha quando tentei usar minha condição / callable / lambda acima, com qualquer uma das funções encadeadas, como
.loc[]
:series_of_tuples.loc[lambda x: x.count('H')==1]
Produz o erro:
KeyError: 'Nível H deve ser igual ao nome (Nenhum)'
Fiquei muito confuso, mas parece que está usando a função Series.count
series_of_tuples.count(...)
, que não é o que eu queria.Admito que uma estrutura de dados alternativa pode ser melhor:
Isso cria uma série de strings (ou seja, concatenando a tupla; juntando os caracteres na tupla em uma única string)
series_of_tuples.apply(''.join)
Então eu posso usar o encadeamento
Series.str.count
series_of_tuples.apply(''.join).str.count('H')==1
fonte