Pada Chapter Fancy Indexing kita memilih banyak elemen sekaligus dengan menuliskan daftar indeks di dalam tanda kurung siku, misalnya harga[[0, 2, 4]]. Cara ini ringkas, tetapi terikat pada sintaks operator: tidak ada tempat menaruh opsi seperti axis dinamis, penulisan hasil ke array lama, atau kebijakan indeks di luar batas. Untuk kebutuhan semacam itu NumPy menyediakan keluarga fungsi np.take, np.put, np.choose, np.compress, dan np.extract.

Kelimanya bekerja seperti operator pengindeksan — mengambil atau menaruh elemen — tetapi berupa panggilan fungsi dengan opsi lebih kaya. Sebagai benang merah, kita memakai data penjualan tiga kota selama tiga bulan.

np.take: Pemilihan dengan Argumen Eksplisit #

Fungsi np.take(a, indices, axis=None, out=None, mode='raise') mengambil elemen a pada posisi indices. Perbedaannya dengan a[indices]: opsi axis sebagai argumen biasa, penulisan hasil ke array lama lewat out, dan kebijakan indeks di luar batas lewat mode.

python
import numpy as np

penjualan = np.array([[120, 95, 210],
                      [80, 110, 60],
                      [150, 70, 180]])
kota = np.array(["Jakarta", "Bandung", "Surabaya"])
print(np.take(kota, [2, 0]))
print(np.take(penjualan, [1, 2], axis=1))
print(penjualan[:, [1, 2]])

Output yang Dihasilkan:

text
['Surabaya' 'Jakarta']
[[ 95 210]
 [110  60]
 [ 70 180]]
[[ 95 210]
 [110  60]
 [ 70 180]]

Mari kita bedah:

  1. Baris 3-5: penjualan adalah matriks 3x3; satu baris mewakili satu kota sesuai urutan kota, dan tiap kolom adalah penjualan satu bulan.
  2. Baris 7: np.take(kota, [2, 0]) tanpa axis mengindeks array satu dimensi secara langsung; hasilnya mengikuti urutan daftar indeks, bukan urutan data.
  3. Baris 8: axis=1 memilih kolom 1 dan 2 dari setiap baris — dua bulan terakhir tiap kota.
  4. Baris 9: padanan fancy indexing memberi hasil yang sama. Bedanya, axis pada np.take boleh berasal dari variabel saat program berjalan, sehingga fungsi utilitas bisa menerima axis sebagai parameter.

Mode clip dan wrap untuk Indeks di Luar Batas #

Default mode='raise' memunculkan IndexError untuk indeks di luar batas. mode='clip' memotong indeks ke batas terdekat, sedangkan mode='wrap' mengulang indeks dari awal seperti operasi modulo.

python
import numpy as np

stok = np.array([12, 7, 20, 5])
indeks = np.array([0, 3, 9])
print(np.take(stok, indeks, mode="clip"))
print(np.take(stok, indeks, mode="wrap"))
try:
    print(stok[indeks])
except IndexError as e:
    print("IndexError:", e)

Output yang Dihasilkan:

text
[12  5  5]
[12  5  7]
IndexError: index 9 is out of bounds for axis 0 with size 4
  1. Baris 5: pada mode="clip" indeks 9 dipotong menjadi 3, sehingga nilai 5 (stok terakhir) tampil dua kali.
  2. Baris 6: pada mode="wrap" indeks 9 dipetakan ke 9 % 4 = 1, sehingga nilai 7 yang diambil.
  3. Baris 8-10: fancy indexing dengan indeks yang sama langsung memunculkan IndexError; pola try/except menjaga blok tetap selesai.

Mode ini berguna bila indeks merupakan hasil perhitungan dan kita ingin perilaku aman tanpa validasi manual.

np.put dan Argumen out pada np.take #

np.put(a, ind, v, mode='raise') adalah kebalikan dari np.take: fungsi tersebut menaruh nilai v pada posisi ind dan mengubah a langsung (in-place). Indeksnya bersifat flat — array diperlakukan sebagai satu barisan memori, tanpa konsep axis — dan mode menerima pilihan yang sama dengan np.take. Sebaliknya, argumen out pada np.take menulis hasil ke array yang sudah tersedia.

python
import numpy as np

penjualan = np.array([120, 95, 210, 80, 150])
np.put(penjualan, [1, 3], [99, 88])
print(penjualan)
target = np.empty(3, dtype=np.int64)
np.take(penjualan, [0, 2, 4], out=target, mode="clip")
print(target)

Output yang Dihasilkan:

text
[120  99 210  88 150]
[120 210 150]
  1. Baris 4-5: nilai 99 ditaruh pada indeks 1 dan 88 pada indeks 3; tidak ada array baru yang dibuat, dan perubahan terlihat saat penjualan dicetak.
  2. Baris 7-8: target disiapkan lebih dulu dengan bentuk dan dtype yang cocok; NumPy menulis hasil np.take langsung ke target tanpa mengalokasikan array sementara — hemat untuk pemanggilan berulang di dalam loop.

np.choose, np.compress, dan np.extract #

np.choose(indeks, daftar) memilih nilai per elemen dari beberapa array kandidat. Sebagai contoh, pelanggan memilih paket harga: 0 berarti tarif reguler, 1 berarti tarif promo.

python
import numpy as np

reguler = np.array([15000, 20000, 18000])
promo = np.array([12000, 17500, 15000])
paket = np.array([0, 1, 0])
print(np.choose(paket, [reguler, promo]))

Output yang Dihasilkan:

text
[15000 17500 18000]
  1. Baris 5-6: untuk posisi ke-i, np.choose mengambil elemen ke-i dari kandidat ke-paket[i]; posisi 0 dan 2 bernilai 0 sehingga diambil dari reguler, posisi 1 bernilai 1 sehingga diambil dari promo. Bila nilai pemilih melebihi jumlah kandidat, np.choose memunculkan ValueError.

np.compress(kondisi, a, axis) memilih potongan utuh sepanjang axis berdasarkan mask boolean; np.extract(kondisi, a) menggabungkan mask dan pengambilan nilai dalam satu panggilan, hasilnya selalu satu dimensi.

python
import numpy as np

penjualan = np.array([[120, 95, 210],
                      [80, 110, 60],
                      [150, 70, 180]])
pilih_kota = np.array([True, False, True])
print(np.compress(pilih_kota, penjualan, axis=0))
print(np.compress(pilih_kota, penjualan, axis=1))
print(np.extract(penjualan[0] > 100, penjualan[0]))

Output yang Dihasilkan:

text
[[120  95 210]
 [150  70 180]]
[[120 210]
 [ 80  60]
 [150 180]]
[120 210]
  1. Baris 7: mask tiga elemen cocok dengan jumlah baris; axis=0 mempertahankan baris ke-0 dan ke-2 (Jakarta dan Surabaya).
  2. Baris 8: axis=1 menerapkan mask yang sama pada kolom; jumlah baris tidak berubah, hanya kolom ke-1 yang lolos seleksi.
  3. Baris 9: np.extract mengambil nilai di atas 100 dari baris pertama, hasilnya array satu dimensi.

Ketiganya berbagi ide dengan mask pada Chapter Boolean Indexing: a[a > 100] bekerja seperti np.extract. np.compress lebih pas bila dimensi hasil harus terjaga, karena seleksi dilakukan per axis.

Kapan Memilih yang Mana #

Fancy indexing tetap pilihan utama untuk kode sehari-hari karena ringkas. Keluarga fungsi ini menonjol pada situasi berikut:

SituasiPilihanAlasan
Axis ditentukan saat program berjalannp.takeaxis bisa menjadi parameter fungsi
Indeks mungkin melebihi batasnp.take(mode=...)clip dan wrap menangani tanpa error
Hasil ditulis ke array lamanp.take(..., out=...)tanpa alokasi array sementara
Mengganti nilai pada posisi tertentunp.putin-place dan bekerja pada indeks flat
Salah satu dari beberapa array kandidatnp.choosemenggantikan if/else per elemen
Baris atau kolom utuh menurut masknp.compressseleksi sepanjang axis
Elemen lolos kondisi, hasil flatnp.extractsatu panggilan untuk mask dan nilai

Pemilihan fungsi menjadi soal mencocokkan kebutuhan, bukan menghafal nama.