Mengambil baris, kolom, atau elemen dengan indeks angka memang luwes, tetapi kebutuhan yang paling sering muncul dalam analisis data adalah menyaring berdasarkan kondisi: “nilai ujian mana saja yang di atas 75?”, “produk mana yang harganya di bawah 20.000 rupiah?”. Menulis indeks satu per satu untuk pertanyaan seperti ini tidak praktis. Boolean indexing menyelesaikannya dengan dua langkah: buat array boolean dari operasi perbandingan, lalu pakai array itu sebagai selektor.

Array boolean yang dipakai sebagai selektor ini disebut mask. Bab ini membahas pembuatan mask, penggabungan beberapa kondisi, dan penerapannya pada array dua dimensi.

Mask Boolean dari Operasi Perbandingan #

Operasi perbandingan pada array berjalan secara vectorization: perbandingan dieksekusi ke semua elemen sekaligus tanpa loop, dan hasilnya array boolean yang bentuknya sama dengan array aslinya.

python
import numpy as np

nilai = np.array([70, 85, 60, 90, 75, 88, 55, 95])
lulus = nilai > 75
print(lulus)
print(nilai[lulus])
print((nilai > 75).sum())

Output yang Dihasilkan:

text
[False  True False  True False  True False  True]
[85 90 88 95]
4

Mari kita bedah:

  1. Baris 3 (nilai > 75): NumPy membandingkan tiap elemen dengan 75 dan menyimpan hasilnya di array boolean lulus yang berbentuk (8,). Posisi True menandai elemen yang memenuhi syarat.
  2. Baris 5 (nilai[lulus]): mask dipakai sebagai selektor. NumPy mengambil hanya elemen pada posisi True, sehingga hasilnya [85 90 88 95] — empat nilai di atas 75.
  3. Baris 6 ((nilai > 75).sum()): menjumlahkan array boolean. Dalam penjumlahan, True dihitung 1 dan False dihitung 0, sehingga hasilnya 4. Pola ini praktis untuk menghitung banyaknya elemen yang lolos kondisi.

Menggabungkan Kondisi dengan &, |, dan ~ #

Beberapa kondisi dapat digabungkan dengan operator logika per elemen: & untuk “dan”, | untuk “atau”, dan ~ untuk negasi. Tiap kondisi wajib dibungkus tanda kurung.

python
import numpy as np

harga = np.array([15000, 4500, 22000, 18500, 30000, 9500])
print(harga[harga < 20000])
print(harga[(harga < 20000) & (harga > 10000)])
print(harga[~(harga < 20000)])

Output yang Dihasilkan:

text
[15000  4500 18500  9500]
[15000 18500]
[22000 30000]

Penjelasan tiap baris:

  1. Baris 4 (harga[harga < 20000]): kondisi ditulis langsung di dalam kurung siku; hasilnya empat harga di bawah 20.000.
  2. Baris 5 ((harga < 20000) & (harga > 10000)): dua mask digabungkan dengan &. Elemen diambil hanya bila kedua kondisi benar, sehingga tersisa [15000 18500].
  3. Baris 6 (~(harga < 20000)): tanda ~ membalik seluruh mask, sehingga yang terambil justru harga yang tidak kurang dari 20.000, yaitu [22000 30000].
python
import numpy as np

harga = np.array([15000, 4500, 22000, 18500, 30000, 9500])
try:
    print(harga[harga < 20000 & harga > 10000])
except ValueError as e:
    print("ValueError:", e)

Output yang Dihasilkan:

text
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Pesan galat tersebut muncul karena Python menganggap ekspresi tanpa tanda kurung sebagai perbandingan berantai, lalu mencoba menilai kebenaran (truth value) satu array boolean secara keseluruhan — sesuatu yang NumPy tolak karena jawabannya tidak pasti. Kebiasaan membungkus tiap kondisi dengan tanda kurung menghindarkan kita dari galat ini.

Boolean Indexing pada Array Dua Dimensi #

Pada array dua dimensi, mask yang dibentang seluruh matriks menghasilkan elemen-elemen yang lolos kondisi, sedangkan mask satu dimensi pada satu kolom dapat dipakai untuk menyaring baris.

python
import numpy as np

penjualan = np.array([
    [120, 85, 200, 65],
    [90, 150, 110, 40],
    [175, 60, 95, 130],
])
rata = penjualan.mean()
print(rata)
print(penjualan[penjualan > rata])
print(penjualan[penjualan > rata].shape)
print(penjualan[penjualan[:, 0] > 100])

Output yang Dihasilkan:

text
110.0
[120 200 150 175 130]
(5,)
[[120  85 200  65]
 [175  60  95 130]]

Mari kita telaah:

  1. Baris 8 (rata = penjualan.mean()): rata-rata seluruh elemen matriks adalah 110.0.
  2. Baris 10 (penjualan[penjualan > rata]): mask dua dimensi memilih semua elemen di atas rata-rata. Hasilnya array satu dimensi [120 200 150 175 130] — elemen diambil menyusuri baris dari kiri ke kanan.
  3. Baris 11: bentuk (5,) menegaskan dua hal penting: hasil boolean indexing selalu array baru (copy), dan hasilnya terlipat menjadi satu dimensi.
  4. Baris 12 (penjualan[penjualan[:, 0] > 100]): mask penjualan[:, 0] > 100 berbentuk (3,) dan menyaring baris, bukan elemen. Baris yang kolom pertamanya di atas 100 ikut terambil utuh, sehingga hasilnya tetap dua dimensi.

Ringkasan Pola Boolean Indexing #

EkspresiArti
mask = a > 75membuat mask boolean dari perbandingan
a[mask] atau a[a > 75]mengambil elemen yang lolos kondisi
(a > 75).sum()menghitung banyaknya elemen yang lolos
(a > 5000) & (a < 20000)irisan dua kondisi (keduanya harus benar)
(a < 5000) | (a > 20000)gabungan dua kondisi (salah satu cukup)
~(a > 75)negasi: elemen yang tidak memenuhi kondisi
a[a[:, 0] > 100]menyaring baris array dua dimensi

Dengan mask, pertanyaan analitik seperti “berapa banyak nilai di atas rata-rata?” cukup dijawab satu baris: (nilai > nilai.mean()).sum(). Gabungan mask inilah fondasi dari penyaringan data yang lebih kompleks pada bab-bab berikutnya.