Je filtre les lignes d'un dataframe par valeurs dans deux colonnes.
Pour une raison quelconque, l'opérateur OR se comporte comme je m'attendrais à ce que l'opérateur AND se comporte et vice versa.
Mon code de test:
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 (|)',])
Et le résultat:
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]
Comme vous pouvez le voir, l' AND
opérateur supprime chaque ligne dans laquelle au moins une valeur est égale -1
. D'autre part, l' OR
opérateur exige que les deux valeurs soient égales à -1
pour les supprimer. Je m'attendrais exactement au résultat opposé. Quelqu'un pourrait-il expliquer ce comportement, s'il vous plaît?
J'utilise pandas 0.13.1.
python
pandas
boolean-logic
Wojciech Walczak
la source
la source
df.query
etpd.eval
semblent bien adaptés à ce cas d'utilisation. Pour plus d'informations sur lapd.eval()
famille de fonctions, leurs caractéristiques et leurs cas d'utilisation, veuillez visiter Évaluation des expressions dynamiques dans les pandas à l'aide de pd.eval () .Réponses:
C'est vrai. N'oubliez pas que vous écrivez la condition en termes de ce que vous voulez conserver , pas en termes de ce que vous voulez laisser tomber. Pour
df1
:Vous dites "conserver les lignes dans lesquelles
df.a
n'est pas -1 etdf.b
n'est pas -1", ce qui revient à supprimer toutes les lignes dans lesquelles au moins une valeur est -1.Pour
df2
:Vous dites "conserver les lignes dans lesquelles soit
df.a
oudf.b
non -1", ce qui revient à supprimer des lignes où les deux valeurs sont -1.PS: un accès enchaîné
df['a'][1] = -1
peut vous causer des ennuis. Il vaut mieux prendre l'habitude d'utiliser.loc
et.iloc
.la source
DataFrame.query()
fonctionne bien ici aussi.df.query('a != -1 or b != -1')
.&
et|
encoreand
etor
?and
etor
ont une sémantique Python de base qui ne peut pas être modifiée&
et|
, d'autre part, ont des méthodes spéciales correspondantes qui contrôlent leur comportement. (Dans les chaînes de requête, bien sûr, nous sommes libres d'appliquer l'analyse de notre choix.)df[True & False]
échouer maisdf[(True) & (False)]
réussit (non testé sur cet exemple)Vous pouvez utiliser query () , c'est-à-dire:
la source
Un peu de théorie de la logique mathématique ici:
"NOT a AND NOT b" équivaut à "NOT (a OR b)" , donc:
"a NOT -1 AND b NOT -1" est équivalent à "NOT (a is -1 OR b is -1)" , qui est l'opposé (Complement) de "(a is -1 OR b is -1)" .
Donc, si vous voulez un résultat exactement opposé, df1 et df2 devraient être comme ci-dessous:
la source