2013-04-14 5 views
100

Mam dziś stosunkowo proste pytanie. Mam obiekt pandy Series zawierający wartości logiczne. Jak mogę uzyskać serię zawierającą logiczną NOT każdej wartości?Jak mogę uzyskać logiczny element NIE z serii PANDA?

Rozważmy na przykład serię zawierającą:

True 
True 
True 
False 

Seria Chciałbym dostać będzie zawierać:

False 
False 
False 
True 

Wydaje się, że powinna być w miarę proste, ale widocznie I ve niesłuszna mój mojo dzisiaj = (

Dzięki!

+0

Istotne jest to, że dane nie zawierają 'object' typy dla poniższe odpowiedzi do działania, więc użyj: '~ df.astype ('bool')' – LearnOPhile

Odpowiedz

115

Aby odwrócić logiczną Series, 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 

Korzystanie Python2.7, NumPy 1.8.0, Pandy 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 

Począwszy od Pandy 0.13.0, seria nie są już podklasy numpy.ndarray; są teraz podklasami pd.NDFrame. Może to mieć coś wspólnego z tym, dlaczego np.invert(s) nie jest już tak szybki jak ~s lub -s.

Zastrzeżenie: timeit wyniki mogą się różnić w zależności od wielu czynników, w tym sprzętu, kompilatora, systemu operacyjnego, Pythona, NumPy i wersji Pand.

+0

Należy zauważyć. Poza tym, że jest znacznie wolniejsza, jaka jest różnica między tyldą a "-'? – blz

+0

Dziwne, faktycznie testowałem 'tyldę', jak wspomniano w dokumentacji, ale nie działało to tak jak' np.invert': S – root

+0

@blz: Przynajmniej na moim komputerze z Ubuntu, z NumPy 1.6.2 , wydajność 'np.invert (s)', '~ s' i' -s' są takie same. – unutbu

8

po prostu dać mu 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

Dosłownie spróbowałem każdego operatora innego niż '-'! Będę o tym pamiętać następnym razem. – blz

4

Można również użyć 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: Różnica w wydajności na Ubuntu 12.04, Python 2.7 pojawia NumPy 1.7.0 - nie wydaje się istnieć użyciu NumPy 1.6 0,2 mimo:

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

Bardzo fajne! Dzięki za testy porównawcze! – blz

6

@ odpowiedź unutbu jest na miejscu, po prostu chciałem dodać ostrzeżenie, że twoja maska ​​musi być dtype bool, a nie "obiekt". To znaczy, twoja maska ​​nie mogła mieć żadnych nanów. Zobacz here - nawet jeśli twoja maska ​​jest teraz wolna od nan, pozostanie "obiektem".

Odwrotność serii "obiektów" nie spowoduje błędu, zamiast tego pojawi się maska ​​śmieciowa, która nie będzie działać zgodnie z oczekiwaniami.

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 

Po rozmowie z kolegami o tym jednym mam wyjaśnienie: To wygląda jak pandy jest powracanie do operatora mnożenie:

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