TLDR; Operator logis di Panda adalah &, |dan ~, dan tanda kurung (...)penting!
Operator Python and, ordan notlogis 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 ( exp1danexp2 ekspresi yang mengevaluasi ke hasil boolean) ...
exp1 and exp2 # Logical AND
exp1 or exp2 # Logical OR
not exp1 # Logical NOT
... akan diterjemahkan ke ...
exp1 & exp2 # Element-wise logical AND
exp1 | exp2 # Element-wise logical OR
~exp1 # Element-wise logical NOT
untuk panda.
Jika dalam proses melakukan operasi logis Anda mendapatkan ValueError, maka Anda harus menggunakan tanda kurung untuk pengelompokan:
(exp1) op (exp2)
Sebagai contoh,
(df['col1'] == x) & (df['col2'] == y)
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:
np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df
A B C
0 5 0 3
1 3 7 9
2 3 5 2
3 4 7 6
4 8 8 1
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 Berlebihan
Sebelum melanjutkan, harap perhatikan kutipan khusus dokumen ini, yang menyatakan
Operasi umum lainnya adalah penggunaan vektor boolean untuk menyaring data. Operator adalah: |untuk or, &untuk and, dan ~untuk not. Ini harus dikelompokkan dengan menggunakan tanda kurung , karena secara default Python akan mengevaluasi ekspresi seperti df.A > 2 & df.B < 3seperti df.A > (2 &
df.B) < 3, sementara pesanan evaluasi yang diinginkan adalah (df.A > 2) & (df.B <
3).
Jadi, dengan mengingat hal ini, elemen bijaksana logis DAN dapat diimplementasikan dengan operator bitwise &:
df['A'] < 5
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'] > 5
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
(df['A'] < 5) & (df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
Dan langkah penyaringan selanjutnya adalah sederhana,
df[(df['A'] < 5) & (df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
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
df['A'] < 5 & df['B'] > 5
Diurai sebagai
df['A'] < (5 & df['B']) > 5
Yang menjadi,
df['A'] < something_you_dont_want > 5
Yang menjadi (lihat dokumen python pada perbandingan operator dirantai ),
(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)
Yang menjadi,
# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2
Yang melempar
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
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:
df['A'].lt(5)
0 True
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df['B'].gt(5)
0 False
1 True
2 False
3 True
4 True
Name: B, dtype: bool
df['A'].lt(5) & df['B'].gt(5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
Lihat bagian tentang Perbandingan Fleksibel. . Untuk meringkas, kami punya
╒════╤════════════╤════════════╕
│ │ Operator │ Function │
╞════╪════════════╪════════════╡
│ 0 │ > │ gt │
├────┼────────────┼────────────┤
│ 1 │ >= │ ge │
├────┼────────────┼────────────┤
│ 2 │ < │ lt │
├────┼────────────┼────────────┤
│ 3 │ <= │ le │
├────┼────────────┼────────────┤
│ 4 │ == │ eq │
├────┼────────────┼────────────┤
│ 5 │ != │ ne │
╘════╧════════════╧════════════╛
Pilihan lain untuk menghindari tanda kurung adalah menggunakan DataFrame.query(atau eval):
df.query('A < 5 and B > 5')
A B C
1 3 7 9
3 4 7 6
Saya telah banyak mendokumentasikan querydan evaldalam 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.
import operator
operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
dtype: bool
df[operator.and_(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
Anda biasanya tidak membutuhkan ini, tetapi berguna untuk mengetahuinya.
Generalisasi: np.logical_and(dan logical_and.reduce)
Alternatif lain adalah menggunakan np.logical_and, yang juga tidak perlu pengelompokan tanda kurung:
np.logical_and(df['A'] < 5, df['B'] > 5)
0 False
1 True
2 False
3 True
4 False
Name: A, dtype: bool
df[np.logical_and(df['A'] < 5, df['B'] > 5)]
A B C
1 3 7 9
3 4 7 6
np.logical_andadalah ufunc (Fungsi Universal) , dan sebagian besar ufunc memiliki reducemetode. Ini berarti lebih mudah untuk digeneralisasikan dengan logical_andjika Anda memiliki beberapa topeng ke AND. Misalnya, untuk DAN topeng m1dan m2dan m3dengan &, Anda harus melakukannya
m1 & m2 & m3
Namun, opsi yang lebih mudah adalah
np.logical_and.reduce([m1, m2, m3])
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):
import operator
cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]
m = np.logical_and.reduce([op(df[c], v) for op, c, v in zip(ops, cols, values)])
m
# array([False, True, False, True, False])
df[m]
A B C
1 3 7 9
3 4 7 6
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 dfatas, katakan Anda ingin mengembalikan semua baris tempat A == 3 atau B == 7.
Bitwise Overloaded |
df['A'] == 3
0 False
1 True
2 True
3 False
4 False
Name: A, dtype: bool
df['B'] == 7
0 False
1 True
2 False
3 True
4 False
Name: B, dtype: bool
(df['A'] == 3) | (df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[(df['A'] == 3) | (df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
Jika Anda belum, baca juga bagian Logical AND di atas, semua peringatan berlaku di sini.
Atau, operasi ini dapat ditentukan dengan
df[df['A'].eq(3) | df['B'].eq(7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
operator.or_
Panggilan di Series.__or__bawah tenda.
operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
dtype: bool
df[operator.or_(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
np.logical_or
Untuk dua kondisi, gunakan logical_or:
np.logical_or(df['A'] == 3, df['B'] == 7)
0 False
1 True
2 True
3 True
4 False
Name: A, dtype: bool
df[np.logical_or(df['A'] == 3, df['B'] == 7)]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
Untuk beberapa topeng, gunakan logical_or.reduce:
np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False, True, True, True, False])
df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]
A B C
1 3 7 9
2 3 5 2
3 4 7 6
TIDAK logis
Diberi topeng, seperti
mask = pd.Series([True, True, False])
Jika Anda perlu membalikkan setiap nilai boolean (sehingga hasil akhirnya [False, False, True]), maka Anda dapat menggunakan salah satu metode di bawah ini.
Bitwise ~
~mask
0 False
1 False
2 True
dtype: bool
Sekali lagi, ekspresi perlu di kurung.
~(df['A'] == 3)
0 True
1 False
2 False
3 True
4 True
Name: A, dtype: bool
Ini panggilan internal
mask.__invert__()
0 False
1 False
2 True
dtype: bool
Tetapi jangan menggunakannya secara langsung.
operator.inv
Secara internal memanggil __invert__Seri.
operator.inv(mask)
0 False
1 False
2 True
dtype: bool
np.logical_not
Ini adalah varian yang numpy.
np.logical_not(mask)
0 False
1 False
2 True
dtype: bool
Catatan, np.logical_anddapat diganti untuk np.bitwise_and, logical_ordengan bitwise_or, dan logical_notdengan invert.