Estou filtrando linhas em um dataframe por valores em duas colunas.
Por alguma razão, o operador OR se comporta como eu esperaria que o operador AND se comportasse e vice-versa.
Meu código de teste:
import pandas as pd
df = pd.DataFrame({'a': range(5), 'b': range(5) })
# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1
df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]
print pd.concat([df, df1, df2], axis=1,
keys = [ 'original df', 'using AND (&)', 'using OR (|)',])
E o resultado:
original df using AND (&) using OR (|)
a b a b a b
0 0 0 0 0 0 0
1 -1 -1 NaN NaN NaN NaN
2 2 2 2 2 2 2
3 -1 3 NaN NaN -1 3
4 4 -1 NaN NaN 4 -1
[5 rows x 6 columns]
Como você pode ver, o AND
operador descarta todas as linhas nas quais pelo menos um valor é igual -1
. Por outro lado, o OR
operador exige que ambos os valores sejam iguais -1
para descartá-los. Eu esperaria exatamente o resultado oposto. Alguém poderia explicar esse comportamento, por favor?
Estou usando pandas 0.13.1.
python
pandas
boolean-logic
Wojciech Walczak
fonte
fonte
df.query
epd.eval
parece ser um bom ajuste para este caso de uso. Para obter informações sobre apd.eval()
família de funções, seus recursos e casos de uso, visite Avaliação de Expressão Dinâmica em pandas usando pd.eval () .Respostas:
Está certo. Lembre-se de que você está escrevendo a condição em termos do que deseja manter , não em termos do que deseja eliminar. Para
df1
:Você está dizendo "mantenha as linhas em que
df.a
não seja -1 edf.b
não seja -1", o mesmo que eliminar todas as linhas em que pelo menos um valor seja -1.Para
df2
:Você está dizendo "mantenha as linhas em que é
df.a
oudf.b
não -1", que é o mesmo que soltar linhas em que os dois valores são -1.PS: acesso encadeado como
df['a'][1] = -1
pode causar problemas. É melhor adquirir o hábito de usar.loc
e.iloc
.fonte
DataFrame.query()
funciona bem aqui também.df.query('a != -1 or b != -1')
.&
e|
sobreand
eor
?and
eor
semântica básica do Python que não pode ser modificada.&
e|
, por outro lado, possuem métodos especiais correspondentes que controlam seu comportamento. (Em cadeias de consulta, é claro, somos livres para aplicar qualquer análise que desejar.) #df[True & False]
falha, masdf[(True) & (False)]
é bem-sucedido (não testado neste exemplo) #Você pode usar query () , ou seja:
fonte
Um pouco de teoria da lógica matemática aqui:
"NOT a AND NOT b" é igual a "NOT (a OR b)" , portanto:
"a NOT -1 AND b NOT -1" é equivalente a "NOT (a é -1 OR b é -1)" , que é o oposto (Complemento) de "(a é -1 OR b é -1)" .
Portanto, se você deseja um resultado exatamente oposto, df1 e df2 devem ser os seguintes:
fonte