2013-04-14 7 views
100

Ho una domanda relativamente semplice, oggi. Ho un oggetto panda Series contenente valori booleani. Come posso ottenere una serie contenente il valore logico NOT di ciascun valore?Come posso ottenere il NON logico element-element di una serie di panda?

Ad esempio, si consideri una serie contenente:

True 
True 
True 
False 

La serie mi piacerebbe ottenere conterrebbe:

False 
False 
False 
True 

Questo sembra che dovrebbe essere ragionevolmente semplice, ma a quanto pare ho' ve smarrito il mio mojo oggi = (

Grazie!

+0

E 'importante che i dati non contengono 'tipi object' per le risposte qui sotto per funzionare, quindi usa: '~ df.astype ('bool')' – LearnOPhile

risposta

115

Per invertire una serie booleano, 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 

Utilizzando 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 

Come di panda 0.13.0, Serie non sono sottoclassi più di numpy.ndarray; ora sono sottoclassi di pd.NDFrame. Questo potrebbe avere qualcosa a che fare con il motivo np.invert(s) non è più veloce come ~s o -s.

Avvertenza: timeit I risultati possono variare a seconda di molti fattori tra cui hardware, compilatore, OS, Python, NumPy e Pandas.

+0

debitamente indicato. Oltre a essere molto più lento, qual è la differenza tra la tilde e '-'? – blz

+0

Per quanto mi riguarda, ho effettivamente testato la 'tilde' come menzionato nella documentazione, ma non ha funzionato come' np.invert': S – root

+0

@blz: Almeno sulla mia macchina Ubuntu, eseguendo NumPy 1.6.2 , le prestazioni di 'np.invert (s)', '~ s' e' -s' sono tutte uguali. – unutbu

8

ho solo dare un sh OT:

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 
+0

Ho letteralmente provato ogni operatore tranne '-'! Lo terrò a mente per la prossima volta. – blz

4

È inoltre possibile utilizzare 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 differenza di prestazioni appare su Ubuntu 12.04, Python 2.7, NumPy 1.7.0 - non sembra esistere utilizzando NumPy 1.6 .2 però:

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 
+0

Molto bello! Grazie per i parametri! – blz

6

La risposta di @ unutbu è azzeccata, volevo solo aggiungere un avviso che la maschera deve essere dtype bool, non "oggetto". Cioè la tua maschera non può avere mai aveva qualche nan. Vedi here - anche se la maschera è ora nan-free, rimarrà di tipo "oggetto".

L'inverso di una serie "oggetto" non genera un errore, ma si otterrà una maschera di immondizia di ints che non funzionerà come previsto.

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 

Dopo aver parlato con i colleghi su questo devo una spiegazione: Sembra che i panda è un ritorno al l'operatore bit a bit:

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