web-dev-qa-db-fra.com

Comment puis-je obtenir les éléments logiques NON d'une série pandas?

J'ai un objet pandas Series contenant des valeurs booléennes. Comment puis-je obtenir une série contenant le NOT logique de chaque valeur?

Par exemple, considérons une série contenant:

True
True
True
False

La série que j'aimerais avoir contiendrait:

False
False
False
True

Cela semble être assez simple, mais apparemment, j’ai égaré mon mojo = (

183
blz

Pour inverser une série booléenne, tilisez ~s :

In [7]: s = pd.Series([True, True, False, True])

In [8]: ~s
Out[8]: 
0    False
1    False
2     True
3    False
dtype: bool

Avec Python2.7, NumPy 1.8.0, Pandas 0.13.1:

In [119]: s = pd.Series([True, True, False, True]*10000)

In [10]:  %timeit np.invert(s)
10000 loops, best of 3: 91.8 µs per loop

In [11]: %timeit ~s
10000 loops, best of 3: 73.5 µs per loop

In [12]: %timeit (-s)
10000 loops, best of 3: 73.5 µs per loop

À partir de Pandas 0.13.0, les séries ne sont plus des sous-classes de numpy.ndarray; ils sont maintenant des sous-classes de pd.NDFrame. Cela pourrait avoir quelque chose à voir avec pourquoi np.invert(s) n'est plus aussi rapide que ~s ou -s.

Mise en garde: timeit les résultats peuvent varier en fonction de nombreux facteurs, notamment le matériel, le compilateur, le système d'exploitation, Python, NumPy et Pandas versions.

211
unutbu

La réponse de @ unutbu est parfaite, je voulais juste ajouter un avertissement indiquant que votre masque doit être dactylographié, pas d'objet. C'est-à-dire que votre masque ne peut avoir jamais jamais eu de nan. Voir ici - même si votre masque est maintenant sans nan, il restera du type 'objet'.

L'inverse d'une série 'object' ne générera pas d'erreur, mais vous obtiendrez un masque de déchets contenant des données inertes qui ne fonctionneront pas comme prévu.

In[1]: df = pd.DataFrame({'A':[True, False, np.nan], 'B':[True, False, True]})
In[2]: df.dropna(inplace=True)
In[3]: df['A']
Out[3]:
0    True
1   False
Name: A, dtype object
In[4]: ~df['A']
Out[4]:
0   -2
0   -1
Name: A, dtype object

Après en avoir parlé à des collègues à propos de celui-ci, j'ai une explication: il semble que pandas revienne à l'opérateur binaire:

In [1]: ~True
Out[1]: -2
18
JSharm

Je viens de tenter le coup:

In [9]: s = Series([True, True, True, False])

In [10]: s
Out[10]: 
0     True
1     True
2     True
3    False

In [11]: -s
Out[11]: 
0    False
1    False
2    False
3     True
12
herrfz

Vous pouvez également utiliser numpy.invert :

_In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: s = pd.Series([True, True, False, True])

In [4]: np.invert(s)
Out[4]: 
0    False
1    False
2     True
3    False
_

EDIT: La différence de performance apparaît sur Ubuntu 12.04, Python 2.7, NumPy 1.7.0 - ne semble pas exister avec NumPy 1.6.2 bien que:

_In [5]: %timeit (-s)
10000 loops, best of 3: 26.8 us per loop

In [6]: %timeit np.invert(s)
100000 loops, best of 3: 7.85 us per loop

In [7]: %timeit ~s
10000 loops, best of 3: 27.3 us per loop
_
5
root