Sebuah vektor harga (3,) kadang perlu diperlakukan sebagai matriks satu baris (1, 3) atau satu kolom (3, 1) — misalnya saat harga harus dijumlahkan dengan potongan per wilayah yang berbentuk matriks. Operasi aritmetika antar array menuntut kesesuaian sumbu, dan sumbu itu kadang harus kita sisipkan sendiri.
np.expand_dims(a, axis) menyisipkan sumbu baru berukuran satu pada posisi axis. Bentuk array berubah, jumlah elemen tidak. Bab ini juga membahas padanan indexed-nya, np.newaxis, serta alasan utama keduanya dipakai: menyiapkan broadcasting.
Menyisipkan Sumbu Baru #
Posisi axis menentukan di mana sumbu berukuran satu disisipkan: axis=0 di depan, axis=1 di belakang untuk array 1-D.
import numpy as np
harga = np.array([15000, 20000, 25000])
print(harga.shape)
baris = np.expand_dims(harga, axis=0)
kolom = np.expand_dims(harga, axis=1)
print(baris.shape, kolom.shape)
print(kolom)Output yang Dihasilkan:
(3,)
(1, 3) (3, 1)
[[15000]
[20000]
[25000]]Baris demi baris:
- Baris 3:
hargaadalah array 1-D berbentuk(3,). - Baris 5 (
expand_dims(harga, axis=0)): sumbu baru disisipkan di depan, menghasilkan(1, 3)— satu baris, tiga kolom. - Baris 6 (
expand_dims(harga, axis=1)): sumbu baru disisipkan di belakang, menghasilkan(3, 1)— tiga baris, satu kolom. - Baris 8 (
print(kolom)): nilai ditampilkan bertumpuk ke bawah; inilah yang disebut vektor kolom.
Kedua hasil memuat nilai yang sama; yang berbeda hanyalah orientasinya. axis=-1 juga sah dan berarti menyisipkan di posisi paling belakang, sama seperti axis=1 untuk array 1-D. Blok berikut membuktikan kedua hal itu sekaligus, termasuk sifat view dari hasilnya:
import numpy as np
harga = np.array([15000, 20000, 25000])
d = np.expand_dims(harga, axis=-1)
print(d.shape)
print(np.shares_memory(d, harga))Output yang Dihasilkan:
(3, 1)
TruePenjelasan:
- Baris 4 (
axis=-1): posisi negatif dihitung dari belakang, sehingga sumbu baru disisipkan setelah sumbu terakhir; bentuknya(3, 1), sama sepertiaxis=1pada array 1-D. - Baris 6 (
np.shares_memory): hasilexpand_dimsadalah view yang berbagi buffer denganharga, sehingga tercetakTrue. Menyisipkan sumbu tidak menyalin data sama sekali.
Padanannya dengan np.newaxis #
Indexed array dengan np.newaxis menghasilkan array yang sama tanpa memanggil fungsi. np.newaxis hanyalah alias untuk None; sumbu baru muncul di posisi di mana np.newaxis ditulis.
import numpy as np
harga = np.array([15000, 20000, 25000])
b1 = harga[np.newaxis, :]
k1 = harga[:, np.newaxis]
print(b1.shape, k1.shape)
print(np.array_equal(b1, np.expand_dims(harga, axis=0)))
print(np.array_equal(k1, np.expand_dims(harga, axis=1)))Output yang Dihasilkan:
(1, 3) (3, 1)
True
TruePenjelasan:
- Baris 4 (
harga[np.newaxis, :]):np.newaxisdi posisi pertama menambah sumbu depan; hasilnya(1, 3). - Baris 5 (
harga[:, np.newaxis]):np.newaxisdi posisi kedua menambah sumbu belakang; hasilnya(3, 1). - Baris 7-8:
np.array_equalmemastikan hasil indexing identik dengan hasilexpand_dims, sehingga keduanya tercetakTrue.
Tabel berikut memetakan keduanya:
| Ekspresi | Bentuk hasil | Sumbu baru berada di |
|---|---|---|
harga[np.newaxis, :] | (1, 3) | depan |
harga[:, np.newaxis] | (3, 1) | belakang |
np.expand_dims(harga, axis=0) | (1, 3) | depan |
np.expand_dims(harga, axis=1) | (3, 1) | belakang |
Persiapan Broadcasting #
Motivasi terbesar sumbu berukuran satu adalah broadcasting: NumPy mengembangkan sumbu berukuran satu agar operasi aritmetika antar bentuk berbeda tetap berjalan. Dengan mengubah vektor harga menjadi kolom dan vektor potongan menjadi baris, satu penjumlahan menghasilkan seluruh kombinasi.
import numpy as np
harga = np.array([15000, 20000, 25000])
potongan = np.array([500, 1000])
kombinasi = harga[:, np.newaxis] + potongan[np.newaxis, :]
print(kombinasi.shape)
print(kombinasi)Output yang Dihasilkan:
(3, 2)
[[15500 16000]
[20500 21000]
[25500 26000]]Mari kita bedah:
- Baris 4:
harga[:, np.newaxis]berbentuk(3, 1); setiap harga menempati satu baris. - Baris 4 (lanjutan):
potongan[np.newaxis, :]berbentuk(1, 2); dua nilai potongan berada dalam satu baris. - Baris 5 (penjumlahan): NumPy mengembangkan
(3, 1)menjadi(3, 2)dan(1, 2)menjadi(3, 2), lalu menjumlahkan; hasilnya(3, 2). Baris pertama adalah15000 + 500dan15000 + 1000, dan seterusnya.
Aturan kapan pengembangan ini boleh terjadi akan dibahas lebih lanjut pada Chapter Memeriksa Kompatibilitas Bentuk dan diperdalam pada Section Broadcasting dan Vectorization. Sebagai gambaran awal: 3 melawan 2 tidak memenuhi syarat karena keduanya lebih besar dari satu dan tidak sama, sehingga penjumlahan harga + potongan tanpa penyesuaian sumbu akan ditolak NumPy. Sumbu berukuran satu pada (3, 1) dan (1, 2) itulah yang memberi izin kepada NumPy untuk mengembangkan kedua sisi menjadi (3, 2).
Orientasi juga menentukan makna hasil: harga[:, np.newaxis] menjadikan setiap harga satu baris (satu harga, banyak potongan), sedangkan harga[np.newaxis, :] menjadikan setiap harga satu kolom. Salah orientasi tidak selalu error; kadang hanya menghasilkan tabel yang tertransposkan dari maksud kita, maka biasakan mencetak hasilnya untuk diperiksa.