Fungsi reshape menyusun ulang seluruh elemen array ke dalam bentuk baru tanpa menambah, mengurangi, atau mengubah nilainya. Topik ini membahas aturan yang mengikat fungsi tersebut, yaitu jumlah elemen yang wajib tetap, urutan pengisian yang mengikuti baris, placeholder -1 untuk satu sumbu otomatis, serta sifat hasilnya sebagai view. Setelah membacanya, bentuk target dari sebuah array dapat ditentukan dengan tepat dan sifat memori hasilnya sudah diketahui sebelum digunakan.
Aturan dasar reshape#
Aturan utama reshape hanya satu, yaitu jumlah elemen sebelum dan sesudah pembentukan ulang harus sama. Bentuk target dinyatakan sebagai pasangan panjang sumbu, dan hasil kali panjang semua sumbunya wajib sama dengan size array asal. Contoh berikut menyusun ulang dua belas nilai ujian yang semula satu dimensi menjadi tiga baris dan empat kolom.
import numpy as np
nilai = np.array([72, 85, 90, 68, 79, 88, 91, 75, 83, 70, 95, 81])
matriks = nilai.reshape(3, 4)
print(matriks)
print(matriks.shape)[[72 85 90 68]
[79 88 91 75]
[83 70 95 81]]
(3, 4)Array hasil berbentuk (3, 4) dengan isi yang tetap sama persis. Pembentukan ulang tidak melakukan operasi aritmetika apa pun, sehingga nilai pertama tetap 72 dan nilai terakhir tetap 81. Yang berubah hanya cara NumPy membaca buffer data, yaitu dari satu deretan panjang menjadi deretan tiga baris.
Urutan pengisian mengikuti baris, sesuai konvensi urutan memori C pada NumPy. Elemen pertama mengisi baris pertama dari kiri ke kanan, kemudian baris kedua, dan seterusnya sampai array terisi penuh. Contoh berikut memperlihatkan urutan itu pada array kecil.
import numpy as np
a = np.arange(6).reshape(2, 3)
print(a)[[0 1 2]
[3 4 5]]Nilai 0, 1, dan 2 menempati baris pertama, sedangkan 3, 4, dan 5 menempati baris kedua. Pemahaman urutan ini penting karena bentuk target yang berbeda, misalnya (3, 2), menghasilkan penempatan nilai yang berbeda pula pada array yang sama.
Placeholder -1 untuk satu sumbu#
Salah satu panjang sumbu pada bentuk target boleh ditulis -1, yang berarti panjang sumbu itu dihitung otomatis. NumPy membagi size array dengan hasil kali panjang sumbu yang sudah dinyatakan, lalu menggunakan hasil baginya sebagai panjang sumbu -1. Trik ini berguna ketika salah satu dimensi sudah diketahui, misalnya jumlah kolom, sedangkan jumlah barisnya ingin mengikuti panjang data.
import numpy as np
a = np.arange(12)
print(a.reshape(3, -1).shape)
print(a.reshape(-1, 6).shape)(3, 4)
(2, 6)Bentuk (3, -1) menghasilkan (3, 4) karena 12 dibagi 3 adalah 4, sedangkan (-1, 6) menghasilkan (2, 6) karena 12 dibagi 6 adalah 2. Placeholder -1 boleh berada di posisi mana pun dalam bentuk target. Yang dilarang hanyalah menuliskannya lebih dari satu kali, karena dua sumbu yang tidak diketahui tidak memiliki jawaban tunggal. Pada praktiknya, -1 paling sering digunakan untuk meratakan array menjadi satu dimensi melalui reshape(-1).
reshape sebagai view#
Apabila susunan memori array asalnya mengizinkan, reshape tidak menyalin data apa pun dan mengembalikan view, yaitu array yang berbagi buffer data dengan asalnya. Sifat ini dapat dibuktikan dengan np.shares_memory, dan akibatnya, mutasi pada hasil reshape terbawa ke array asal. Contoh berikut memperlihatkan keduanya.
import numpy as np
a = np.arange(12)
b = a.reshape(3, 4)
print(np.shares_memory(a, b))
b[0, 0] = 100
print(a[0])True
100Keluaran True menunjukkan bahwa b berbagi memori dengan a. Penugasan b[0, 0] = 100 kemudian mengubah elemen pertama buffer yang sama, sehingga a[0] yang tercetak berikutnya ikut bernilai 100. Perilaku ini tidak menimbulkan peringatan, sehingga array asal wajib dilindungi dengan .copy() apabila hasil reshape akan dimutasi dan data asal harus tetap utuh.
Meskipun berbagi memori, hasil reshape adalah objek array yang baru, bukan array asalnya sendiri. Keduanya dapat dibedakan dengan operator is dan atribut .base.
import numpy as np
a = np.arange(12)
b = a.reshape(3, 4)
print(b is a)
print(b.base is a)False
Trueb is a bernilai False karena b adalah objek ndarray yang terpisah, sedangkan b.base is a bernilai True karena buffer milik b dipinjam dari a. Pembedaan antara objek dan memori ini penting ketika kode memeriksa identitas array, bukan sekadar isinya.
Alternatif lain adalah menetapkan bentuk secara langsung melalui penugasan a.shape = .... Cara ini mengubah bentuk array itu sendiri tanpa membuat objek baru, sehingga tidak ada variabel tambahan yang perlu dikelola.
import numpy as np
a = np.arange(12)
a.shape = (3, 4)
print(a.shape)
print(a[0])(3, 4)
[0 1 2 3]Kata kuncinya adalah “apabila” pada awal bagian ini. View hanya mungkin apabila pola lompatan memori array asal dapat menyatakan bentuk baru tersebut. Apabila tidak, NumPy senyap membuat salinan, dan ikatan memori hilang tanpa pemberitahuan apa pun. Contoh berikut membentuk ulang transpose dari sebuah array, dan hasilnya bukan lagi view.
import numpy as np
a = np.arange(6).reshape(2, 3)
t = a.T
c = t.reshape(2, 3)
print(np.shares_memory(a, c))FalseArray t tersusun dalam urutan memori kolom, sehingga bentuk (2, 3) pada urutan baris tidak dapat dinyatakan sebagai pola lompatan yang beraturan. NumPy menjawabnya dengan salinan, dan np.shares_memory melaporkan False. Kondisi ini menegaskan bahwa klaim view pada reshape selalu diperiksa, bukan diasumsikan.
Kesalahan umum#
Kesalahan pertama adalah meminta bentuk yang jumlah elemennya tidak cocok. Pemanggilan reshape(2, 5) pada array dua belas elemen meminta hasil kali panjang sumbu sebesar 10, sedangkan array memuat 12 elemen, sehingga NumPy menolaknya dengan ValueError.
import numpy as np
a = np.arange(12)
try:
a.reshape(2, 5)
except ValueError as e:
print(f"{type(e).__name__}: {e}")ValueError: cannot reshape array of size 12 into shape (2,5)Pesan error menyebut kedua angka yang berselisih, yaitu ukuran array 12 dan bentuk tujuan (2, 5). Cara membacanya adalah menghitung hasil kali panjang sumbu bentuk tujuan, lalu menyamakannya dengan size array asal. Bila salah satu sumbu memang fleksibel, tuliskan sumbu itu sebagai -1 agar NumPy yang menghitungnya.
Kesalahan kedua adalah menulis -1 lebih dari satu kali. Bentuk (-1, -1) meminta dua sumbu dihitung otomatis, dan NumPy tidak memiliki dasar untuk menentukan keduanya sekaligus.
import numpy as np
a = np.arange(12)
try:
a.reshape(-1, -1)
except ValueError as e:
print(f"{type(e).__name__}: {e}")ValueError: can only specify one unknown dimensionPesan can only specify one unknown dimension menyatakan batas tersebut secara harfiah. Perbaikannya adalah menyatakan salah satu sumbu dengan angka yang pasti, atau menghitung salah satunya di luar NumPy sebelum bentuk target disusun.
Ringkasan#
reshapemenyusun ulang elemen ke bentuk baru dengan syarat hasil kali panjang sumbu bentuk target sama dengansizearray asal.- Pengisian elemen mengikuti baris sesuai urutan memori C, dan satu sumbu boleh digantikan placeholder -1 yang dihitung otomatis.
- Apabila susunan memori mengizinkan,
reshapemengembalikan view yang berbagi memori dengan array asal sehingga mutasi padanya terbawa, sedangkan penugasana.shape = ...mengubah bentuk tanpa membuat objek baru. - Apabila view tidak mungkin, NumPy membuat salinan tanpa pemberitahuan, sehingga klaim view wajib diperiksa dengan
np.shares_memory.
Referensi#
- numpy.reshape — NumPy — Dokumentasi resmi reshape beserta aturan -1 dan sifat view hasilnya.
- Copies and views — NumPy — Penjelasan resmi kapan operasi NumPy menghasilkan view dan kapan salinan dibuat.