Pembentukan ulang dengan reshape

Aturan reshape dan placeholder -1.

Daftar isi

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.

python Contoh: reshape dua dimensi dari dua belas nilai
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)
text Keluaran
[[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.

python Contoh: urutan pengisian mengikuti baris
import numpy as np

a = np.arange(6).reshape(2, 3)
print(a)
text Keluaran
[[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.

python Contoh: placeholder -1 pada satu sumbu
import numpy as np

a = np.arange(12)
print(a.reshape(3, -1).shape)
print(a.reshape(-1, 6).shape)
text Keluaran
(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.

python Contoh: membuktikan reshape sebagai view
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])
text Keluaran
True
100

Keluaran 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.

python Contoh: objek baru dengan memori yang sama
import numpy as np

a = np.arange(12)
b = a.reshape(3, 4)
print(b is a)
print(b.base is a)
text Keluaran
False
True

b 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.

python Contoh: penugasan shape langsung pada array
import numpy as np

a = np.arange(12)
a.shape = (3, 4)
print(a.shape)
print(a[0])
text Keluaran
(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.

python Contoh: reshape yang memaksa salinan
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))
text Keluaran
False

Array 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.

python Contoh: error jumlah elemen tidak cocok
import numpy as np

a = np.arange(12)
try:
    a.reshape(2, 5)
except ValueError as e:
    print(f"{type(e).__name__}: {e}")
text Keluaran
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.

python Contoh: error dua placeholder -1
import numpy as np

a = np.arange(12)
try:
    a.reshape(-1, -1)
except ValueError as e:
    print(f"{type(e).__name__}: {e}")
text Keluaran
ValueError: can only specify one unknown dimension

Pesan 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#

  • reshape menyusun ulang elemen ke bentuk baru dengan syarat hasil kali panjang sumbu bentuk target sama dengan size array asal.
  • Pengisian elemen mengikuti baris sesuai urutan memori C, dan satu sumbu boleh digantikan placeholder -1 yang dihitung otomatis.
  • Apabila susunan memori mengizinkan, reshape mengembalikan view yang berbagi memori dengan array asal sehingga mutasi padanya terbawa, sedangkan penugasan a.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#