Saya bekerja dengan indeks boolean di Pandas. Pertanyaannya adalah mengapa pernyataan itu:
a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]
berfungsi dengan baik sedangkan
a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]
keluar dengan kesalahan?
Contoh:
a=pd.DataFrame({'x':[1,1],'y':[10,20]})
In: a[(a['x']==1)&(a['y']==10)]
Out: x y
0 1 10
In: a[(a['x']==1) and (a['y']==10)]
Out: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
and != &
. Theand
operator dalam Python tidak bisa ditimpa, sedangkan&
operator (__and__
) bisa. Karenanya pilihan penggunaan&
dalam numpy dan panda.Jawaban:
Kapan kamu berkata
Anda secara implisit meminta Python untuk mengonversi
(a['x']==1)
dan(a['y']==10)
ke nilai boolean.Array NumPy (dengan panjang lebih dari 1) dan objek Pandas seperti Seri tidak memiliki nilai boolean - dengan kata lain, mereka meningkatkan
bila digunakan sebagai nilai boolean. Itu karena tidak jelas kapan harus Benar atau Salah . Beberapa pengguna mungkin menganggap mereka Benar jika panjangnya tidak nol, seperti daftar Python. Orang lain mungkin menginginkannya sebagai Benar hanya jika semua elemennya Benar. Orang lain mungkin ingin itu Benar jika salah satu elemennya Benar.
Karena ada begitu banyak harapan yang saling bertentangan, para perancang NumPy dan Pandas menolak untuk menebak, dan malah menaikkan ValueError.
Sebaliknya, Anda harus eksplisit, dengan memanggil
empty()
,all()
atauany()
metode untuk menunjukkan perilaku mana yang Anda inginkan.Namun dalam kasus ini, sepertinya Anda tidak ingin evaluasi boolean, Anda ingin elemen- logical-and-logical. Itulah yang dilakukan oleh
&
operator biner:mengembalikan array boolean.
By the way, seperti catatan alexpmil , tanda kurung wajib karena
&
memiliki prioritas operator lebih tinggi daripada==
. Tanpa tanda kurung,a['x']==1 & a['y']==10
akan dievaluasi sepertia['x'] == (1 & a['y']) == 10
yang pada gilirannya akan setara dengan perbandingan rantai(a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10)
. Itu adalah ekspresi bentukSeries and Series
. Penggunaanand
dengan dua Seri lagi akan memicu yang samaValueError
seperti di atas. Itu sebabnya tanda kurung wajib.sumber
x and y
memicu evaluasibool(x)
danbool(y)
. Python "pertama mengevaluasix
; jikax
salah, nilainya dikembalikan; jika tidak,y
dievaluasi dan nilai yang dihasilkan dikembalikan." Jadi sintaksisx and y
tidak dapat digunakan untuk elemen-wised logical-dan karena hanyax
atauy
dapat dikembalikan. Sebaliknya,x & y
pemicux.__and__(y)
dan__and__
metode dapat didefinisikan untuk mengembalikan apa pun yang kita suka.==
klausa adalah wajib .a['x']==1 & a['y']==10
mengembalikan kesalahan yang sama seperti pada pertanyaan.TLDR; Operator logis di Panda adalah
&
,|
dan~
, dan tanda kurung(...)
penting!Operator Python
and
,or
dannot
logis dirancang untuk bekerja dengan skalar. Jadi Pandas harus melakukan yang lebih baik dan mengesampingkan operator bitwise untuk mencapai versi fungsionalitas vektor (elemen-bijaksana).Jadi berikut ini di python (
exp1
danexp2
ekspresi yang mengevaluasi ke hasil boolean) ...... akan diterjemahkan ke ...
untuk panda.
Jika dalam proses melakukan operasi logis Anda mendapatkan
ValueError
, maka Anda harus menggunakan tanda kurung untuk pengelompokan:Sebagai contoh,
Dan seterusnya.
Boolean Indexing : Operasi yang umum adalah menghitung topeng boolean melalui kondisi logis untuk menyaring data. Panda menyediakan tiga operator:
&
untuk logika AND,|
untuk logika OR, dan~
untuk logika TIDAK.Pertimbangkan pengaturan berikut:
Logis dan
Untuk
df
atas, katakan Anda ingin mengembalikan semua baris di mana A <5 dan B> 5. Ini dilakukan dengan menghitung masker untuk setiap kondisi secara terpisah, dan menggunakan mereka.&
Operator Bitwise BerlebihanSebelum melanjutkan, harap perhatikan kutipan khusus dokumen ini, yang menyatakan
Jadi, dengan mengingat hal ini, elemen bijaksana logis DAN dapat diimplementasikan dengan operator bitwise
&
:Dan langkah penyaringan selanjutnya adalah sederhana,
Tanda kurung digunakan untuk mengganti urutan presedensi default dari operator bitwise, yang memiliki prioritas lebih tinggi atas operator kondisional
<
dan>
. Lihat bagian Prioritas Operator di python docs.Jika Anda tidak menggunakan tanda kurung, ekspresi dievaluasi salah. Misalnya, jika Anda secara tidak sengaja mencoba sesuatu seperti
Diurai sebagai
Yang menjadi,
Yang menjadi (lihat dokumen python pada perbandingan operator dirantai ),
Yang menjadi,
Yang melempar
Jadi, jangan membuat kesalahan itu! 1
Menghindari Pengelompokan Tanda Kurung
Perbaikan sebenarnya cukup sederhana. Sebagian besar operator memiliki metode terikat yang sesuai untuk DataFrames. Jika masing-masing topeng dibangun menggunakan fungsi alih-alih operator bersyarat, Anda tidak perlu lagi mengelompokkan menurut parens untuk menentukan urutan evaluasi:
Lihat bagian tentang Perbandingan Fleksibel. . Untuk meringkas, kami punya
Pilihan lain untuk menghindari tanda kurung adalah menggunakan
DataFrame.query
(ataueval
):Saya telah banyak mendokumentasikan
query
daneval
dalam Evaluasi Ekspresi Dinamis dalam panda menggunakan pd.eval () .operator.and_
Memungkinkan Anda untuk melakukan operasi ini secara fungsional. Panggilan internal
Series.__and__
yang terkait dengan operator bitwise.Anda biasanya tidak membutuhkan ini, tetapi berguna untuk mengetahuinya.
Generalisasi:
np.logical_and
(danlogical_and.reduce
)Alternatif lain adalah menggunakan
np.logical_and
, yang juga tidak perlu pengelompokan tanda kurung:np.logical_and
adalah ufunc (Fungsi Universal) , dan sebagian besar ufunc memilikireduce
metode. Ini berarti lebih mudah untuk digeneralisasikan denganlogical_and
jika Anda memiliki beberapa topeng ke AND. Misalnya, untuk DAN topengm1
danm2
danm3
dengan&
, Anda harus melakukannyaNamun, opsi yang lebih mudah adalah
Ini sangat kuat, karena memungkinkan Anda membangun di atasnya dengan logika yang lebih kompleks (misalnya, secara dinamis menghasilkan topeng dalam pemahaman daftar dan menambahkan semuanya):
1 - Saya tahu saya mengomel tentang hal ini, tapi tolong tahan dengan saya. Ini adalah kesalahan pemula yang sangat , sangat umum, dan harus dijelaskan dengan seksama.
Logis atau
Untuk yang di
df
atas, katakan Anda ingin mengembalikan semua baris tempat A == 3 atau B == 7.Bitwise Overloaded
|
Jika Anda belum, baca juga bagian Logical AND di atas, semua peringatan berlaku di sini.
Atau, operasi ini dapat ditentukan dengan
operator.or_
Panggilan di
Series.__or__
bawah tenda.np.logical_or
Untuk dua kondisi, gunakan
logical_or
:Untuk beberapa topeng, gunakan
logical_or.reduce
:TIDAK logis
Diberi topeng, seperti
Jika Anda perlu membalikkan setiap nilai boolean (sehingga hasil akhirnya
[False, False, True]
), maka Anda dapat menggunakan salah satu metode di bawah ini.Bitwise
~
Sekali lagi, ekspresi perlu di kurung.
Ini panggilan internal
Tetapi jangan menggunakannya secara langsung.
operator.inv
Secara internal memanggil
__invert__
Seri.np.logical_not
Ini adalah varian yang numpy.
Catatan,
np.logical_and
dapat diganti untuknp.bitwise_and
,logical_or
denganbitwise_or
, danlogical_not
denganinvert
.sumber
|
, yang setara dengannumpy.bitwise_or
, alih-alihnumpy.logical_or
. Bolehkah saya bertanya mengapa? Bukankahnumpy.logical_or
dirancang untuk tugas ini secara khusus? Mengapa menambahkan beban untuk melakukannya secara bitwise untuk setiap pasangan elemen?|
untuk operasi boolean elemen-bijaksana. Tetapi bagi saya, dokumentasi itu lebih merupakan "tutorial", dan sebaliknya, saya merasa referensi API ini lebih dekat ke sumber kebenaran: numpy.bitwise_or dan numpy.logical_or - jadi saya mencoba memahami apa yang ada dijelaskan di sini.Sangat penting untuk menyadari bahwa Anda tidak dapat menggunakan salah satu operator logis Python (
and
,or
ataunot
) padapandas.Series
ataupandas.DataFrame
s (sama halnya Anda tidak dapat menggunakannya padanumpy.array
s dengan lebih dari satu elemen). Alasan mengapa Anda tidak dapat menggunakan itu adalah karena mereka secara implisit memanggilbool
operan mereka yang melempar Pengecualian karena struktur data ini memutuskan bahwa boolean dari sebuah array bersifat ambigu:Saya memang membahas hal ini lebih luas dalam jawaban saya untuk "Nilai kebenaran dari suatu Seri adalah ambigu. Gunakan a.empty, a.bool (), a.item (), a.any () atau a.all ()" Q + A .
Fungsi logis NumPys
Namun NumPy menyediakan unsur-bijaksana setara operasi untuk operator ini sebagai fungsi yang dapat digunakan pada
numpy.array
,pandas.Series
,pandas.DataFrame
, atau lainnya (sesuai)numpy.array
subclass:and
telahnp.logical_and
or
telahnp.logical_or
not
telahnp.logical_not
numpy.logical_xor
yang tidak memiliki setara Python tetapi logis "eksklusif atau" operasiJadi, pada dasarnya, seseorang harus menggunakan (dengan asumsi
df1
dandf2
adalah panda DataFrames):Fungsi bitwise dan operator bitwise untuk boolean
Namun jika Anda memiliki boolean NumPy array, panda Series, atau panda DataFrames Anda juga bisa menggunakan fungsi bitwise elemen-bijaksana (untuk booleans mereka - atau setidaknya harus - tidak dapat dibedakan dari fungsi logis):
np.bitwise_and
atau&
operatornp.bitwise_or
atau|
operatornp.invert
(atau aliasnp.bitwise_not
) atau~
operatornp.bitwise_xor
atau^
operatorBiasanya operator digunakan. Namun ketika dikombinasikan dengan operator pembanding kita harus ingat untuk membungkus perbandingan dalam tanda kurung karena operator bitwise memiliki prioritas lebih tinggi daripada operator pembanding :
Ini mungkin menjengkelkan karena operator logis Python memiliki prioritas lebih rendah daripada operator perbandingan sehingga Anda biasanya menulis
a < 10 and b > 10
(di manaa
danb
misalnya bilangan bulat sederhana) dan tidak perlu tanda kurung.Perbedaan antara operasi logis dan bitwise (pada non-boolean)
Sangat penting untuk menekankan bahwa bit dan operasi logis hanya setara untuk array NumPy boolean (dan boolean Series & DataFrames). Jika ini tidak mengandung boolean maka operasi akan memberikan hasil yang berbeda. Saya akan menyertakan contoh menggunakan array NumPy tetapi hasilnya akan serupa untuk struktur data panda:
Dan karena NumPy (dan juga panda) melakukan hal yang berbeda untuk array indeks boolean ( Boolean atau "mask" ) dan indeks integer ( array array ), hasil pengindeksan juga akan berbeda:
Tabel ringkasan
Di mana operator logis tidak bekerja untuk array NumPy , Seri panda, dan DataFrames panda. Yang lain bekerja pada struktur data ini (dan objek Python sederhana) dan elemen kerja. Namun hati-hati dengan invert bitwise pada Python
bool
s karena bool akan ditafsirkan sebagai bilangan bulat dalam konteks ini (misalnya~False
pengembalian-1
dan~True
pengembalian-2
).sumber