¿Cómo puedo obtener el NOT lógico por elementos de una serie de pandas?

Resuelto Louis Thibault asked hace 11 años • 7 respuestas

Tengo un Seriesobjeto pandas que contiene valores booleanos. ¿ Cómo puedo obtener una serie que contenga la lógica NOTde cada valor?

Por ejemplo, considere una serie que contenga:

True
True
True
False

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

False
False
False
True

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

Louis Thibault avatar Apr 14 '13 17:04 Louis Thibault
Aceptado

Para invertir una serie booleana, utilice~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é ya np.invert(s)no es tan rápido como ~so -s.

Advertencia: timeitlos resultados pueden variar dependiendo de muchos factores, incluido el hardware, el compilador, el sistema operativo, las versiones de Python, NumPy y Pandas.

unutbu avatar Apr 14 '2013 12:04 unutbu

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 nunca pudo haber tenido la de ninguna abuela. Vea aquí : incluso si su máscara ahora no contiene nan, seguirá siendo del tipo "objeto".

La inversa de una serie de 'objetos' no arrojará un error; en su lugar, obtendrá una máscara de basura de enteros que no funcionará como esperaba.

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 colegas sobre esto, tengo una explicación: parece que pandas está volviendo al operador bit a bit:

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

Como dice @geher, puedes convertirlo a bool con astype antes de invertir con ~

~df['A'].astype(bool)
0    False
1     True
Name: A, dtype: bool
(~df['A']).astype(bool)
0    True
1    True
Name: A, dtype: bool
JSharm avatar Mar 10 '2017 15:03 JSharm

Solo le doy 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
herrfz avatar Apr 14 '2013 10:04 herrfz