Data sensor gudang bisa tersimpan sebagai (sensor, waktu, frekuensi), sementara fungsi visualisasi menuntut (frekuensi, sensor, waktu). Untuk pengaturan sumbu yang presisi pada array tiga dimensi ke atas, dua nama menukar posisi sumbu: np.swapaxes dan np.moveaxis. Keduanya terdengar mirip, tetapi semantiknya berbeda dan hasilnya tidak sama.
Bab ini mendemonstrasikan keduanya pada array yang sama, membandingkan pemetaan elemennya, dan membuktikan bahwa keduanya mengembalikan view.
Menukar Dua Sumbu dengan swapaxes #
np.swapaxes(a, axis1, axis2) mempertukarkan posisi dua sumbu; sumbu lain tetap di tempatnya. Kedua argumen menerima indeks negatif, sehingga np.swapaxes(data, 0, -1) sah dan berarti menukar sumbu pertama dengan sumbu terakhir — hasilnya sama dengan menukar sumbu 0 dan 2 pada array 3-D.
import numpy as np
data = np.arange(24).reshape(2, 3, 4)
hasil = np.swapaxes(data, 0, 2)
print(data.shape, "->", hasil.shape)
print(data[0, 1, 2], hasil[2, 1, 0])Output yang Dihasilkan:
(2, 3, 4) -> (4, 3, 2)
6 6Baris demi baris:
- Baris 3: data
(2, 3, 4); anggap 2 wilayah, 3 produk, 4 triwulan. - Baris 4 (
np.swapaxes(data, 0, 2)): sumbu 0 dan sumbu 2 dipertukarkan, sehingga bentuk menjadi(4, 3, 2). Sumbu 1 (produk) tidak bergeser. - Baris 5 (uji pemetaan): aturannya
hasil[x, y, z] == data[z, y, x]. Elemendata[0, 1, 2]bernilai6dan setelah penukaran menempatihasil[2, 1, 0]; keduanya tercetak6 6.
Memindahkan Sumbu dengan moveaxis #
np.moveaxis(a, source, destination) mengambil satu atau beberapa sumbu, mengeluarkannya dari posisi asal, lalu menyisipkannya di posisi tujuan. Sumbu yang tidak disebut mempertahankan urutan relatifnya.
import numpy as np
data = np.arange(24).reshape(2, 3, 4)
hasil = np.moveaxis(data, 0, -1)
print(data.shape, "->", hasil.shape)
print(data[0, 1, 2], hasil[1, 2, 0])Output yang Dihasilkan:
(2, 3, 4) -> (3, 4, 2)
6 6Penjelasan:
- Baris 4 (
np.moveaxis(data, 0, -1)): sumbu 0 dikeluarkan dari depan, sumbu 1 dan 2 maju menjaga urutan, lalu sumbu 0 disisipkan di posisi terakhir (-1). Urutan sumbu baru adalah(1, 2, 0), sehingga bentuknya(3, 4, 2). - Baris 5 (uji pemetaan): aturannya
hasil[x, y, z] == data[z, x, y]. Elemendata[0, 1, 2]yang sama kini berada dihasil[1, 2, 0]; keduanya bernilai6.
Baik source maupun destination pada moveaxis juga menerima tuple, sehingga beberapa sumbu bisa dipindahkan sekaligus dengan satu pemanggilan — misalnya np.moveaxis(data, (0, 1), (2, 0)). Untuk array tiga dimensi, satu sumbu saja sudah mencakup kebanyakan kebutuhan nyata.
Hubungan dengan transpose #
Kedua fungsi ini sebenarnya kasus khusus dari transposisi: setiap hasil mereka bisa ditulis ulang sebagai .transpose() dengan tuple axes. Membuktikannya sekaligus menguatkan pemahaman kita tentang tuple axes:
import numpy as np
data = np.arange(24).reshape(2, 3, 4)
print(np.array_equal(np.swapaxes(data, 0, 2), data.transpose(2, 1, 0)))
print(np.array_equal(np.moveaxis(data, 0, -1), data.transpose(1, 2, 0)))Output yang Dihasilkan:
True
TruePenjelasan:
- Baris 4: menukar sumbu 0 dan 2 setara dengan
transpose(2, 1, 0), karena setelah penukaran urutan sumbunya(2, 1, 0); hasilnya tercetakTrue. - Baris 5: memindahkan sumbu 0 ke belakang setara dengan
transpose(1, 2, 0), karena sumbu tersisa(1, 2)maju dan sumbu 0 diletakkan terakhir; hasilnya jugaTrue.
Dengan pemahaman ini kita bebas memilih bentuk penulisan: swapaxes dan moveaxis menyatakan maksud secara eksplisit, sedangkan transpose memberi kendali penuh atas seluruh urutan sumbu. Dalam kode produksi, penulisan yang menyatakan maksud biasanya lebih mudah dirawat, sebab pembaca tidak perlu membayangkan seluruh urutan sumbu hanya untuk memahami satu penukaran.
Perbandingan Semantik dan Sifat View #
Perbedaan keduanya baru terlihat ketika kita membaca hasil dengan indeks yang sama. Kode berikut membandingkan elemen [2, 1, 0] dari kedua hasil, menguji mutasi, dan memeriksa berbagi memori.
import numpy as np
data = np.arange(24).reshape(2, 3, 4)
swap = np.swapaxes(data, 0, 2)
move = np.moveaxis(data, 0, -1)
print(swap.shape, move.shape)
print(swap[2, 1, 0], move[2, 1, 0])
swap[0, 0, 0] = 999
print(data[0, 0, 0])
print(np.shares_memory(swap, data), np.shares_memory(move, data))Output yang Dihasilkan:
(4, 3, 2) (3, 4, 2)
6 9
999
True TrueMari kita bedah:
- Baris 6 (
print(swap.shape, move.shape)): input yang sama menghasilkan dua bentuk berbeda,(4, 3, 2)versus(3, 4, 2). Ini bukti pertama bahwa keduanya bukan operasi yang sama. - Baris 7: pada indeks
[2, 1, 0], hasil swap bernilai6(menunjukdata[0, 1, 2]), sedangkan hasil move bernilai9(menunjukdata[0, 2, 1]). Pemetaan elemennya memang berbeda. - Baris 8-9 (uji mutasi): mengubah
swap[0, 0, 0]ikut mengubahdata[0, 0, 0]menjadi999; swap adalah view. - Baris 10 (
np.shares_memory): kedua fungsi mengembalikan view yang berbagi buffer dengandata, sehingga keduanya tercetakTrue.
Tabel berikut merangkum perbandingannya:
| Aspek | np.swapaxes(data, 0, 2) | np.moveaxis(data, 0, -1) |
|---|---|---|
| Aksi | tukar posisi dua sumbu | pindahkan sumbu ke posisi tujuan |
Bentuk hasil dari (2, 3, 4) | (4, 3, 2) | (3, 4, 2) |
| Peta elemen | hasil[x, y, z] = data[z, y, x] | hasil[x, y, z] = data[z, x, y] |
| Jenis hasil | view | view |