Array dua dimensi menyimpan data dalam baris dan kolom, sehingga aksesnya memerlukan indeks baris dan indeks kolom sekaligus. Topik ini membahas pengambilan satu elemen, satu baris, dan satu kolom pada array dua dimensi, kemudian membandingkan bentuk rantai indeks a[1][0] dengan bentuk indeks majemuk a[1, 0]. Array contoh yang digunakan berukuran tiga kali empat dan berisi angka berurutan agar setiap hasil mudah dilacak ke posisinya.
Akses elemen dengan dua indeks#
Elemen tunggal array dua dimensi diakses dengan menuliskan indeks baris dan indeks kolom dalam satu kurung siku yang dipisahkan koma, seperti a[1, 2]. Kedua indeks berbasis nol, dan urutannya adalah baris terlebih dahulu kemudian kolom. Indeks negatif juga berlaku pada kedua sumbu, sehingga -1 selalu menunjuk baris atau kolom paling akhir.
import numpy as np
a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(a.shape)
print(a[1, 2])
print(a[-1, -1])(3, 4)
7
12Atribut .shape menunjukkan bahwa a memiliki tiga baris dan empat kolom. Pemanggilan a[1, 2] berarti baris indeks 1, yaitu baris kedua, pada kolom indeks 2, yaitu kolom ketiga, dan hasilnya adalah 7. Bentuk a[-1, -1] mengambil elemen pada baris terakhir dan kolom terakhir, yaitu 12, tanpa perlu menghitung panjang kedua sumbu.
Satu indeks tunggal tanpa koma, misalnya a[0], berarti memilih seluruh baris pertama dan menurunkan dimensi array dari dua menjadi satu. Kombinasi indeks tunggal dengan indeks negatif juga sah, sehingga a[-2, 0] berarti elemen pertama pada baris kedua dari akhir, yaitu 5. Perilaku penurunan dimensi inilah yang menjadi dasar pengambilan baris pada bagian berikutnya.
Mengambil baris dan kolom#
Satu baris diambil hanya dengan menuliskan indeks barisnya, misalnya a[1], atau secara eksplisit dengan a[1, :] yang berarti baris indeks 1 pada seluruh kolom. Tanda : di posisi kolom berarti seluruh elemen pada sumbu tersebut dipilih, persis seperti pemakaiannya pada slicing satu dimensi. Kolom diambil dengan pola yang berkebalikan, yaitu membiarkan sumbu baris terbuka dan membatasi indeks kolom, misalnya a[:, 0] untuk kolom pertama.
import numpy as np
a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(a[1])
print(a[1, :])
print(a[:, 0])
print(a[:, 0].shape)[5 6 7 8]
[5 6 7 8]
[1 5 9]
(3,)Baris kedua muncul dua kali karena a[1] dan a[1, :] memberikan hasil yang sama, yaitu [5 6 7 8]. Kolom pertama diambil oleh a[:, 0] dan menghasilkan [1 5 9]. Perhatikan bahwa bentuk hasilnya (3,), yaitu array satu dimensi, bukan kolom tegak berbentuk (3, 1). Perbedaan bentuk (n,) dengan (n, 1) menjadi penting pada operasi antar array dan dibahas pada modul Broadcasting.
Kesetaraan a[1] dengan a[1, :] muncul karena indeks yang ditiadakan diperlakukan sebagaimana potongan penuh, yaitu seluruh sumbu yang tersisa dipilih. Aturan yang sama menjelaskan mengapa a[:, 1] mengambil kolom kedua dan bukan baris. Pada array berdimensi lebih tinggi, setiap sumbu yang tidak diberi indeks tetap dipilih penuh, sehingga pola penulisannya konsisten dengan array dua dimensi.
Hasil baris tersebut bukan salinan, melainkan view yang menunjuk memori array asalnya. Penugasan pada elemen baris karenanya ikut mengubah array asal, seperti ditunjukkan kode berikut.
import numpy as np
a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
baris = a[1]
baris[0] = 50
print(a)[[ 1 2 3 4]
[50 6 7 8]
[ 9 10 11 12]]Penugasan baris[0] = 50 menulis pada memori yang sama dengan elemen a[1, 0], sehingga array asal ikut berubah. Perilaku yang sama berlaku untuk kolom hasil a[:, 0] karena keduanya merupakan hasil pengindeksan dasar yang menghasilkan view. Kapan ikatan ini terjadi dan cara memutusnya dibahas pada topik View versus salinan.
Rantai indeks versus indeks majemuk#
Python mengizinkan dua cara untuk mengambil satu elemen dari array dua dimensi, yaitu rantai indeks a[1][0] dan indeks majemuk a[1, 0]. Bentuk rantai mengindeks hasil pengindeksan, yaitu mengambil baris terlebih dahulu, kemudian mengambil elemen dari baris itu, sedangkan bentuk majemuk menyerahkan kedua indeks sekaligus dalam satu kurung siku. Keduanya mengembalikan nilai yang sama.
import numpy as np
a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(a[1][0])
print(a[1, 0])5
5Perbedaannya ada pada mekanisme. Bentuk a[1][0] mengerjakan dua operasi berturut-turut dan menghasilkan satu array perantara berupa baris, sedangkan a[1, 0] menyelesaikan akses dalam satu operasi tanpa array perantara. Untuk kasus sederhana selisihnya kecil, tetapi kebiasaan menulis bentuk majemuk lebih aman karena kedua bentuk hanya setara pada indeks tunggal. Pada indeks berbentuk array, misalnya a[[0, 1], [1, 0]], bentuk majemuk mengambil pasangan elemen tersebar, sedangkan bentuk rantai menyusun ulang baris terlebih dahulu, sehingga hasil keduanya sama sekali berbeda. Perbandingan rincinya dibahas pada topik Fancy indexing.
Kesalahan umum#
- Menukar urutan indeks. Pada array yang tidak simetris,
a[2, 1]dana[1, 2]menunjuk elemen yang berbeda, dan kekeliruan urutan ini tidak memunculkan error apa pun sehingga hasilnya diam-diam salah. Perbaikannya adalah mengikuti urutan baku baris dulu, kolom kemudian, pada seluruh kode. - Menggunakan indeks yang melewati batas. Pemanggilan
a[3, 0]pada array tiga baris memunculkanIndexErrorsebagaimana kode di bawah. Perbaikannya adalah memeriksa.shapesebelum mengindeks, terutama ketika indeks berasal dari perhitungan. - Mengira
a[1]adalah salinan independen. Baris yang diambil ternyata view, sehingga mutasi padanya bocor ke array asal. Perbaikannya adalah memanggil.copy()bila baris akan dimodifikasi tanpa menyentuh array asal. - Mengira
a[:, 0]menghasilkan kolom dua dimensi. Hasilnya justru vektor satu dimensi berbentuk(3,), sehingga operasi yang menuntut orientasi kolom perlua[:, :1]ataureshape. Perbaikannya adalah mencetak.shapehasil akses kolom sebelum dipakai pada operasi berikutnya.
import numpy as np
a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
try:
print(a[3, 0])
except IndexError as e:
print(f"IndexError: {e}")IndexError: index 3 is out of bounds for axis 0 with size 3Keempat kekeliruan di atas tidak terlihat dari sekilas pandang kode. Hanya kekeliruan indeks melewati batas yang memunculkan IndexError, dan itu pun baru terjadi ketika program berjalan, sedangkan tiga kekeliruan lainnya berjalan tanpa error apa pun. Kebiasaan mencetak .shape sebelum operasi lanjutan adalah penangkal yang murah bagi semuanya.
Ringkasan#
- Elemen array dua dimensi diakses dengan
a[i, j], yaitu indeks baris terlebih dahulu lalu indeks kolom, keduanya berbasis nol dan mendukung indeks negatif. a[1]dana[1, :]mengambil satu baris, sedangkana[:, 0]mengambil satu kolom dalam bentuk array satu dimensi(n,).a[1][0]dana[1, 0]mengembalikan nilai sama, tetapi bentuk majemuk menyelesaikan akses dalam satu operasi dan menjadi kebiasaan menulis yang disarankan.- Baris hasil pengindeksan adalah view, sehingga mutasi padanya ikut mengubah array asal.
Referensi#
- Indexing on ndarrays — NumPy — Panduan resmi pengindeksan multidimensi, termasuk akses baris, kolom, dan indeks majemuk.
- Indexing routines — NumPy — Rujukan teknis aturan pengindeksan ndarray beserta bentuk hasilnya.