Satu kondisi jarang cukup. Penentuan siswa berprestasi biasanya menuntut dua syarat sekaligus — nilai mencapai batas minimal dan kehadiran penuh — sementara daftar siswa yang perlu dikejar kehadirannya cukup memenuhi salah satu syarat saja. Chapter Operasi Perbandingan menghasilkan mask per kondisi; chapter ini menggabungkan mask-mask itu menjadi satu keputusan.

Agenda bab:

  • Menggabungkan mask dengan & (dan), | (atau), dan ~ (negasi).
  • Jebakan and/or Python serta kewajiban tanda kurung.
  • Menyimpulkan seluruh array dengan np.all dan np.any.

Menggabungkan mask dengan &, |, dan ~ #

Ketiga operator boolean NumPy bekerja per elemen pada dua mask (atau satu mask untuk ~). Kita gabungkan mask kelulusan nilai dengan mask kehadiran penuh:

python
import numpy as np

nilai = np.array([80, 65, 90, 75, 60])
kehadiran = np.array([1, 1, 0, 1, 1])
lulus_nilai = nilai >= 75
penuh_kehadiran = kehadiran == 1
print(lulus_nilai)
print(penuh_kehadiran)
print(lulus_nilai & penuh_kehadiran)
print(lulus_nilai | penuh_kehadiran)
print(~lulus_nilai)
print(np.array_equal(~(lulus_nilai & penuh_kehadiran), ~lulus_nilai | ~penuh_kehadiran))

Output yang Dihasilkan:

text
[ True False  True  True False]
[ True  True False  True  True]
[ True False False  True False]
[ True  True  True  True  True]
[False  True False False  True]
True
  1. Baris 4-5: dua mask berbentuk (5,) — mask tidak harus lahir dari >= saja; ==, <, dan kawan-kawan sama saja.
  2. Baris 9 (lulus_nilai & penuh_kehadiran): True hanya pada posisi yang kedua masknya True — siswa pertama dan keempat memenuhi dua syarat sekaligus.
  3. Baris 10 (lulus_nilai | penuh_kehadiran): True ketika salah satu syarat terpenuhi; semua siswa memenuhi minimal satu syarat.
  4. Baris 11 (~lulus_nilai): ~ membalik setiap nilai — inilah daftar siswa yang gagal di syarat nilai.
  5. Baris 12: hasil True membuktikan hukum De Morgan berlaku pada mask: ~(A & B) identik dengan ~A | ~B.
OperatorArti pada maskPadanan logika
&keduanya benarAND
|salah satu benarOR
~membalik nilaiNOT

Kurung wajib dan jebakan and/or #

Dua kebiasaan dari Python biasa justru menjebak ketika dipakai pada array. Pertama, kata kunci and/or tidak bisa dipakai pada mask. Kedua, & dihitung lebih dahulu dibanding operator perbandingan, sehingga tanda kurung menjadi wajib:

python
import numpy as np

nilai = np.array([80, 65, 90, 75, 60])
kehadiran = np.array([1, 1, 0, 1, 1])
try:
    hasil = (nilai >= 75) and (kehadiran == 1)
except ValueError as e:
    print("ValueError:", e)
tanpa_kurung = nilai >= 75 & kehadiran
print(tanpa_kurung)
dengan_kurung = (nilai >= 75) & (kehadiran == 1)
print(dengan_kurung)

Output yang Dihasilkan:

text
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
[ True  True  True  True  True]
[ True False False  True False]
  1. Blok try (baris 5-8): and menuntut satu nilai kebenaran, sedangkan mask berisi banyak nilai. Python menolak menebak dan melempar ValueError; pesannya sendiri sudah menyarankan a.any() atau a.all().
  2. Baris 9 (nilai >= 75 & kehadiran): karena & dihitung lebih dahulu, ekspresi ini sama artinya dengan nilai >= (75 & kehadiran). Hasilnya kelima posisi True — jawaban yang keliru tanpa satu pun pesan kesalahan.
  3. Baris 11 ((nilai >= 75) & (kehadiran == 1)): dengan tanda kurung di kedua kondisi, hasilnya benar dan sama dengan baris 9 pada bagian sebelumnya.

Menyimpulkan dengan np.all dan np.any #

np.all dan np.any memadatkan sebuah mask menjadi kesimpulan: np.all bernilai True hanya bila semua elemen True, sedangkan np.any cukup satu elemen True. Keduanya juga menerima axis agar kesimpulan dihitung per baris atau per kolom:

python
import numpy as np

banyak = np.array([
    [75, 80, 90],
    [70, 60, 95],
    [65, 55, 40],
])
print(np.all(banyak >= 75, axis=1))
print(np.any(banyak >= 75, axis=0))

Output yang Dihasilkan:

text
[ True False False]
[ True  True  True]
  1. Baris 8 (np.all(..., axis=1)): axis=1 berarti kesimpulan dihitung melintasi kolom, sehingga kita mendapat satu jawaban per baris — baris mana yang semua ulangannya mencapai 75. Hanya siswa pertama yang lulus penuh.
  2. Baris 9 (np.any(..., axis=0)): axis=0 menghitung per kolom — ulangan mana yang paling sedikit satu nilainya mencapai 75. Ketiga kolom memenuhi.
  3. Tanpa argumen axis, kedua fungsi mengembalikan satu bool untuk seluruh array — seperti yang dipakai pesan ValueError pada bagian sebelumnya sebagai saran pengganti and.