¿Cómo puedo obtener el elemento lógico NO de una serie de pandas?

Tengo un objeto de la Series pandas que contiene valores booleanos. ¿Cómo puedo obtener una serie que contenga el NOT lógico de cada valor?

Por ejemplo, considere una serie que contiene:

 True True True False 

La serie que me gustaría obtener contendría:

 False False False True 

Esto parece que debería ser bastante simple, pero aparentemente he perdido mi mojo = (

Para invertir una serie booleana, use ~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 

Usando 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 

A partir de Pandas 0.13.0, las series ya no son subclases de numpy.ndarray ; ahora son subclases de pd.NDFrame . Esto podría tener algo que ver con por qué np.invert(s) ya no es tan rápido como ~s o -s .

Advertencia: los resultados de timeit pueden variar dependiendo de muchos factores, incluyendo hardware, comstackdor, SO, Python, NumPy y versiones de Pandas.

La respuesta de @unutbu es acertada, solo quería agregar una advertencia de que su máscara debe ser dtype bool, no “objeto”. Es decir, tu máscara no puede haber tenido nunca una nan. Consulte aquí : incluso si su máscara ahora está libre de nanómetros, seguirá siendo del tipo ‘objeto’.

La inversa de una serie de ‘objetos’ no generará un error, en su lugar, obtendrá una máscara de ints que no funcionará como espera.

 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 

Después de hablar con mis colegas sobre este tema, tengo una explicación: parece que los pandas están volviendo al operador de bitwise:

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

Acabo de darle una oportunidad:

 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 

También puedes usar 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 

EDITAR: La diferencia en el rendimiento aparece en Ubuntu 12.04, Python 2.7, NumPy 1.7.0 – aunque parece que no existe utilizando NumPy 1.6.2:

 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