Boolean indexing mengembalikan nilai elemen yang lolos kondisi. Dua kebutuhan lain sering muncul di sekitarnya: mencari posisi elemen yang memenuhi syarat, atau mengganti nilai secara kondisional — “tandai tiap nilai sebagai Lulus atau Tidak Lulus”, atau “nolkan semua angka di bawah 100”. Untuk kebutuhan tersebut NumPy menyediakan fungsi np.where, yang punya tiga bentuk pemakaian:

  1. np.where(kondisi) — mengembalikan posisi (indeks) elemen yang memenuhi kondisi.
  2. np.where(kondisi, x, y) — memilih nilai dari x atau y per elemen, menggantikan if-else yang biasa kita tulis dengan loop.
  3. np.where pada array dua dimensi — mengembalikan pasangan indeks baris dan kolom.

Bentuk 1: np.where(kondisi) untuk Mencari Posisi #

Tanpa argumen tambahan, np.where bekerja seperti mencari alamat: hasilnya tuple berisi array indeks dari elemen yang bernilai True pada kondisi.

python
import numpy as np

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

penjualan = np.array([
    [120, 85, 200, 65],
    [90, 150, 110, 40],
    [175, 60, 95, 130],
])
print(np.where(penjualan > 110))
print(penjualan[np.where(penjualan > 110)])

Output yang Dihasilkan:

text
(array([1, 3, 5, 7]),)
(array([0, 0, 1, 2, 2]), array([0, 2, 1, 0, 3]))
[120 200 150 175 130]

Mari kita bedah:

  1. Baris 4 (np.where(nilai > 80)): pada array satu dimensi, hasilnya tuple berisi satu array indeks: (array([1, 3, 5, 7]),). Tanda koma di akhir adalah penulisan tuple Python untuk satu anggota; isi tuple itulah array indeksnya. Elemen 85, 90, 88, 95 berada di posisi ke-1, ke-3, ke-5, dan ke-7.
  2. Baris 11 (np.where(penjualan > 110)): pada array dua dimensi, hasilnya tuple berisi dua array: array pertama menyimpan indeks baris, array kedua indeks kolom. Keduanya dipasangkan satu per satu, sehingga pasangan (0, 0), (0, 2), (1, 1), (2, 0), dan (2, 3) menunjuk lima elemen di atas 110.
  3. Baris 12 (penjualan[np.where(penjualan > 110)]): hasil tuple tersebut dapat langsung dipakai sebagai fancy indexing, dan mengembalikan elemennya: [120 200 150 175 130] — persis hasil penjualan[penjualan > 110].

Bentuk 2: np.where(kondisi, x, y) untuk Memilih Dua Nilai #

Dengan tiga argumen, np.where menjadi pemilih nilai: tiap posisi diisi x bila kondisi True, atau y bila kondisi False. Seluruh proses berjalan sebagai vectorization, tanpa loop Python.

python
import numpy as np

nilai = np.array([70, 85, 60, 90, 75, 88, 55, 95])
status = np.where(nilai >= 75, "Lulus", "Tidak Lulus")
print(status)
print(status.dtype)

penjualan = np.array([
    [120, 85, 200, 65],
    [90, 150, 110, 40],
    [175, 60, 95, 130],
])
koreksi = np.where(penjualan < 100, 0, penjualan)
print(koreksi)

Output yang Dihasilkan:

text
['Tidak Lulus' 'Lulus' 'Tidak Lulus' 'Lulus' 'Lulus' 'Lulus' 'Tidak Lulus'
 'Lulus']
<U11
[[120   0 200   0]
 [  0 150 110   0]
 [175   0   0 130]]

Yang terjadi di balik layar:

  1. Baris 4 (np.where(nilai >= 75, "Lulus", "Tidak Lulus")): NumPy menelusuri kondisi per elemen dan memilih string yang sesuai. Nilai 70 gagal memenuhi syarat sehingga menjadi “Tidak Lulus”, sedangkan 75 tepat pada batas sehingga “Lulus”.
  2. Baris 6 (status.dtype): dtype hasilnya <U11, diambil dari string terpanjang di antara kedua pilihan, yaitu “Tidak Lulus” yang berisi 11 karakter. Karena kedua cabang berupa string, hasilnya array string, bukan angka.
  3. Baris 13 (np.where(penjualan < 100, 0, penjualan)): kedua cabang boleh berupa array. Di sini y adalah penjualan sendiri, sehingga elemen yang tidak memenuhi syarat tetap memakai nilainya, dan hanya nilai di bawah 100 yang diganti 0. Array penjualan asli tidak ikut berubah karena np.where menghasilkan array baru.

Bentuk 3: where pada Satu Kolom dan Perbandingannya dengan Boolean Indexing #

Bentuk ketiga bukan sintaks baru, melainkan penerapan dua bentuk sebelumnya pada array dua dimensi: mask dapat dibangun dari satu kolom, lalu np.where memilih label untuk tiap barisnya.

python
import numpy as np

penjualan = np.array([
    [120, 85, 200, 65],
    [90, 150, 110, 40],
    [175, 60, 95, 130],
])
label = np.where(penjualan[:, 0] > 100, "Target tercapai", "Belum")
print(label)

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

Output yang Dihasilkan:

text
['Target tercapai' 'Belum' 'Target tercapai']
[85 90 88 95]
[1 3 5 7]

Penjelasan singkat:

  1. Baris 8 (penjualan[:, 0] > 100): kolom pertama (penjualan Buku per cabang) disaring menjadi mask tiga elemen. np.where kemudian menghasilkan satu label untuk tiap cabang: Bandung dan Medan mencapai target, Semarang belum.
  2. Baris 11 vs 12: dua output terakhir memperlihatkan perbedaan inti. nilai[nilai > 80] mengembalikan nilai elemen yang lolos, sedangkan np.where(nilai > 80)[0] mengembalikan indeks-nya. [0] dibutuhkan karena hasil np.where berbentuk tuple.
KebutuhanAlat yang tepatHasil
mengambil elemen yang lolos kondisia[kondisi]array elemen (copy)
mencari posisi elemen yang lolosnp.where(kondisi)tuple berisi array indeks
mengganti nilai secara kondisionalnp.where(kondisi, x, y)array baru selebar kondisi

Dengan tabel ini, pemilihan alat menjadi sederhana: butuh datanya, pakai boolean indexing; butuh alamatnya atau perlu menggabungkan hasil seleksi dengan indeks lain, pakai np.where; butuh mengubah nilai berdasarkan syarat, pakai bentuk tiga argumennya.