DataLens

Reshaping, stacking, dan splitting

Ubah shape array tanpa mengubah datanya, rekatkan array, dan potong menjadi beberapa bagian.

Level: Menengah · 9 menit baca

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Idenya

Data jarang datang dalam shape yang kamu butuhkan. Dua belas angka bulanan seharusnya menjadi grid kuartal 4 × 3. Sebuah list nilai harus menjadi satu kolom untuk scikit-learn. Data bulan ini harus direkatkan di bawah data bulan lalu. NumPy punya sekumpulan kecil alat untuk ini, dan semuanya berbagi satu prinsip: angkanya tetap sama, hanya susunannya yang berubah.

reshape

Ini revenue bulanan selama setahun sebagai satu baris panjang berisi 12 angka. Tim keuangan menginginkannya per kuartal: empat baris yang masing-masing berisi tiga bulan. Angkanya tidak berubah, hanya susunannya, dan itulah persis yang dilakukan reshape:

import numpy as np

monthly = np.array([335, 357, 388, 408, 410, 440, 452, 431, 470, 495, 520, 610])
quarters = monthly.reshape(4, 3)
print(quarters)
print(quarters.sum(axis=1))      # total per kuartal
[[335 357 388]
 [408 410 440]
 [452 431 470]
 [495 520 610]]
[1080 1258 1353 1625]

reshape(4, 3) mengisi shape baru baris demi baris: 3 nilai pertama menjadi baris 0 (Q1), 3 berikutnya baris 1, dan seterusnya. Jumlah total elemen harus tetap sama (4 × 3 = 12):

monthly.reshape(5, 3)
ValueError: cannot reshape array of size 12 into shape (5,3)

Biarkan NumPy menghitung satu dimensi dengan menulis -1:

print(monthly.reshape(-1, 3).shape)    # "3 kolom, baris sebanyak yang diperlukan"
print(monthly.reshape(2, -1).shape)    # "2 baris, kolom sebanyak yang diperlukan"
(4, 3)
(2, 6)

Baris menjadi kolom: shape (n, 1)

Library machine learning mengharapkan input X berbentuk 2-D: satu baris per contoh, satu kolom per fitur. Satu fitur yang disimpan sebagai array 1-D harus menjadi kolom:

ad_spend = np.array([5.0, 7.5, 6.0, 9.0])
print(ad_spend.shape)
X = ad_spend.reshape(-1, 1)
print(X.shape)
print(X)
(4,)
(4, 1)
[[5. ]
 [7.5]
 [6. ]
 [9. ]]

Itulah perbaikan untuk error terkenal scikit-learn "Expected 2D array, got 1D array instead". Dua penulisan lain melakukan hal yang sama: ad_spend[:, np.newaxis] dan np.expand_dims(ad_spend, axis=1).

Flatten: kembali ke 1-D

Kebalikannya juga umum: sebuah fungsi atau grafik menginginkan satu deret panjang berisi nilai, sementara kamu punya grid. Flatten menaruh semua elemen kembali ke satu baris:

print(quarters.ravel())
print(quarters.flatten())
[335 357 388 408 410 440 452 431 470 495 520 610]
[335 357 388 408 410 440 452 431 470 495 520 610]

Keduanya mengembalikan elemen dalam urutan baris. ravel mengembalikan view kalau bisa (cepat, berbagi data); flatten selalu menyalin (aman untuk diubah).

Transpose: tukar baris dan kolom

Kadang data datang terbalik: kamu ingin bulan sebagai baris dan kuartal sebagai kolom, tapi yang datang sebaliknya. Transpose membalik grid pada diagonalnya, sehingga baris menjadi kolom dan kolom menjadi baris:

print(quarters.T)
print(quarters.T.shape)
[[335 408 452 495]
 [357 410 431 520]
 [388 440 470 610]]
(3, 4)

.T mengubah grid 4 kuartal × 3 bulan menjadi 3 × 4. Kamu akan membutuhkannya setiap kali data datang "terbalik", dan terus-menerus di aljabar linear.

Stacking: merekatkan array

Data sering datang terpotong-potong. Kamu mungkin mendapat Januari sampai Maret untuk dua toko di satu file dan April sampai Juni di file lain, padahal kamu butuh keduanya sebagai satu tabel enam bulan. np.concatenate menggabungkan array di sepanjang axis yang sudah dimilikinya: axis=1 menaruhnya berdampingan (menambah kolom), dan axis=0 menaruhnya bertumpuk (menambah baris):

h1 = np.array([[120, 135, 150], [80, 85, 90]])   # 2 toko × 3 bulan
h2 = np.array([[160, 155, 170], [88, 95, 100]])
print(np.concatenate([h1, h2], axis=1))   # bersebelahan: lebih banyak bulan
print(np.concatenate([h1, h2], axis=0))   # di atas-bawah: lebih banyak baris
[[120 135 150 160 155 170]
 [ 80  85  90  88  95 100]]
[[120 135 150]
 [ 80  85  90]
 [160 155 170]
 [ 88  95 100]]

Fungsi bantu yang lebih ramah adalah np.vstack (vertikal: menambah baris) dan np.hstack (horizontal: menambah kolom):

new_store = np.array([40, 45, 43])
print(np.vstack([h1, new_store]))
[[120 135 150]
 [ 80  85  90]
 [ 40  45  43]]

np.column_stack membangun tabel dari array 1-D yang dipakai sebagai kolom, cara umum untuk merakit fitur:

price = np.array([185, 320, 95])
cost = np.array([110, 210, 52])
table = np.column_stack([price, cost, price - cost])
print(table)
[[185 110  75]
 [320 210 110]
 [ 95  52  43]]

Shape harus sama di setiap axis kecuali axis tempat kamu menggabungkan, kalau tidak NumPy memunculkan error yang menyebut ketidakcocokannya.

Splitting

Kebalikan dari stacking. np.split memotong menjadi bagian-bagian yang sama besar; np.array_split mengizinkan yang tidak sama:

first_half, second_half = np.split(monthly, 2)
print(first_half, second_half)

for part in np.array_split(np.arange(10), 3):
    print(part)
[335 357 388 408 410 440] [452 431 470 495 520 610]
[0 1 2 3]
[4 5 6]
[7 8 9]

Kamu juga bisa memotong di posisi tertentu: np.split(monthly, [3, 6]) memotong sebelum index 3 dan sebelum index 6, menghasilkan tiga bagian.

Mengapa ini penting untuk kode yang bersih

Reshaping adalah tempat bug shape bersembunyi. Kebiasaan yang bersih: tulis shape yang diharapkan di komentar atau periksa tepat setelah reshape (assert X.shape == (n, 1)). Dan utamakan reshape(-1, 1) daripada menulis panjangnya secara manual, supaya kodenya tetap berfungsi saat datanya bertambah.

Rangkuman

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.