Bagaimana saya bisa mendapatkan elemen-logis BUKAN dari Seri panda?

229

Saya memiliki Seriesobjek panda yang berisi nilai boolean. Bagaimana saya bisa mendapatkan seri yang berisi logika NOTdari setiap nilai?

Misalnya, pertimbangkan seri yang berisi:

True
True
True
False

Seri yang ingin saya dapatkan akan berisi:

False
False
False
True

Sepertinya ini seharusnya cukup sederhana, tetapi ternyata saya salah meletakkan mojo = (

blz
sumber
1
Adalah penting bahwa data tidak mengandung objecttipe untuk jawaban di bawah ini berfungsi, jadi gunakan:~ df.astype('bool')
LearnOPhile
Saya telah menulis tentang semua operator logis di posting ini . Pos juga mencakup alternatif.
cs95

Jawaban:

260

Untuk membalikkan Seri boolean, gunakan~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

Menggunakan 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

Pada Pandas 0.13.0, Seri tidak lagi subclass dari numpy.ndarray; mereka sekarang adalah subclass dari pd.NDFrame. Ini mungkin ada hubungannya dengan mengapa np.invert(s)tidak lagi secepat ~satau -s.

Peringatan: timeithasil dapat bervariasi tergantung pada banyak faktor termasuk perangkat keras, kompiler, OS, Python, NumPy dan versi Pandas.

unutbu
sumber
Sepatutnya dicatat. Selain lebih lambat, apa perbedaan antara tilde dan -?
blz
Wierd, saya benar-benar menguji tildeseperti yang disebutkan dalam dokumentasi, tetapi tidak melakukan hal yang sama seperti np.invert: S
root
@blz: Setidaknya di mesin Ubuntu saya, menjalankan NumPy 1.6.2, kinerja np.invert(s), ~sdan -ssemuanya sama.
unutbu
@ akar: Saya tidak yakin mengapa ada perbedaan besar dalam hasil timeit kami, tapi itu pasti bisa terjadi. OS dan versi NumPy apa yang Anda gunakan?
unutbu
Juga di Ubuntu, tetapi menggunakan NumPy 1.7.0 ... ( np.bitwise_not(s)melakukan hal yang sama seperti np.inverse).
root
32

@ unutbu jawaban tepat, hanya ingin menambahkan peringatan bahwa topeng Anda harus dtype bool, bukan 'objek'. Yaitu masker Anda tidak dapat memiliki pernah punya nan ini. Lihat di sini - bahkan jika topeng Anda bebas nan sekarang, itu akan tetap menjadi tipe 'objek'.

Kebalikan dari seri 'objek' tidak akan menimbulkan kesalahan, sebaliknya Anda akan mendapatkan topeng sampah int yang tidak akan berfungsi seperti yang Anda harapkan.

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

Setelah berbicara dengan rekan tentang hal ini, saya memiliki penjelasan: Sepertinya panda kembali ke operator bitwise:

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

Seperti kata @geher, Anda dapat mengubahnya menjadi bool dengan astype sebelum Anda kebalikan dengan ~

~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
sumber
dalam contoh Anda, mask keluaran ints dapat dikonversi ke seri bool yang Anda inginkan dengan .astype(bool)eg~df['A'].astype(bool)
geher
Ini bekerja karena astype(bool)terjadi sebelum ~ ~df['A'].astype(bool)vs(~df['A']).astype(bool)
JSharm
16

Saya hanya mencobanya:

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
sumber
Saya benar-benar mencoba setiap operator selain -! Saya akan mengingat hal ini untuk waktu berikutnya.
blz
6

Anda juga dapat menggunakan 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: Perbedaan kinerja muncul di Ubuntu 12.04, Python 2.7, NumPy 1.7.0 - tampaknya tidak ada menggunakan 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
akar
sumber
itu mungkin tidak benar pada platform yang berbeda. Menangkan 7, python 3.6.3 numpy 1.13.3, panda 0.20.3, (-s) akan menjadi yang tercepat, (~ s) adalah yang kedua, dan np.invert adalah yang paling lambat
gaozhidf
0

NumPy lebih lambat karena ia memasukkan input ke nilai boolean (jadi None dan 0 menjadi False dan yang lainnya menjadi True).

import pandas as pd
import numpy as np
s = pd.Series([True, None, False, True])
np.logical_not(s)

Memberi anda

0    False
1     True
2     True
3    False
dtype: object

sedangkan ~ s akan crash. Dalam kebanyakan kasus, tilde akan menjadi pilihan yang lebih aman daripada NumPy.

Panda 0,25, Jumlah 1,17

atap
sumber