Agregasi dengan parameter axis menghilangkan satu sumbu dari hasil, sedangkan dua keluarga operasi lain memberikan pilihan yang berbeda. Topik ini membahas parameter keepdims yang mempertahankan jumlah dimensi hasil agregasi, serta operasi kumulatif cumsum dan cumprod yang tidak mengecilkan array sama sekali. Ketiganya sering muncul bersama dalam kode analisis data, dan keepdims menjadi fondasi penyelarasan bentuk pada operasi broadcasting, yakni mekanisme NumPy untuk menyatukan array dengan bentuk yang berbeda.
keepdims mempertahankan jumlah dimensi#
Parameter keepdims diterima oleh fungsi reduksi seperti np.sum dan np.mean. Nilai defaultnya False, sehingga sumbu yang diringkas hilang dari hasil. Apabila diisi True, sumbu tersebut tetap ada dengan panjang 1, sehingga jumlah dimensi array hasil sama dengan jumlah dimensi array asalnya.
import numpy as np
skor = np.array([[80, 92, 78, 88], [85, 74, 90, 79], [70, 82, 76, 84]])
r = np.sum(skor, axis=0)
print(r.shape)
k = np.sum(skor, axis=0, keepdims=True)
print(k.shape)
print(k)(4,)
(1, 4)
[[235 248 244 251]]Kedua hasil memuat nilai yang persis sama, yaitu total setiap kolom, tetapi bentuknya berbeda. Tanpa keepdims, hasilnya array satu dimensi (4,). Dengan keepdims=True, hasilnya array dua dimensi (1, 4), yaitu satu baris berisi empat kolom, dan perbedaan itu terlihat dari sepasang kurung siku ganda pada tampilannya.
Sifat yang sama berlaku pada array satu dimensi. Reduksi pada array satu dimensi biasanya menghasilkan bilangan tunggal, sedangkan dengan keepdims=True hasilnya tetap berupa array dengan satu sumbu berpanjang 1.
import numpy as np
nilai = np.array([72, 85, 60, 90, 78, 88])
k = np.sum(nilai, axis=0, keepdims=True)
print(k.shape)
print(k)(1,)
[473]Bentuk (1,) memuat nilai yang sama dengan nilai.sum(), yaitu 473, tetapi tetap berupa array alih-alih bilangan tunggal. Bentuk seperti ini berguna ketika hasil agregasi akan digabungkan kembali dengan array lain, karena jumlah dimensinya tidak berubah.
keepdims dan penyelarasan bentuk#
Bentuk (1, 4) atau (3, 1) yang dihasilkan keepdims bukan sekadar formalitas, melainkan kunci ketika hasil agregasi akan dipadukan kembali dengan array asalnya. Operasi aritmetika antar array menuntut bentuk yang selaras, dan aturan penyelarasan itulah yang disebut broadcasting. Contoh klasiknya adalah membagi setiap elemen dengan rata-rata barisnya masing-masing, yaitu normalisasi baris.
import numpy as np
skor = np.array([[80, 92, 78, 88], [85, 74, 90, 79], [70, 82, 76, 84]])
try:
hasil = skor / skor.mean(axis=1)
except ValueError as e:
print(f"{type(e).__name__}: {e}")
hasil = skor / skor.mean(axis=1, keepdims=True)
print(hasil.shape)
print(np.round(hasil, 2))ValueError: operands could not be broadcast together with shapes (3,4) (3,)
(3, 4)
[[0.95 1.09 0.92 1.04]
[1.04 0.9 1.1 0.96]
[0.9 1.05 0.97 1.08]]Pemanggilan tanpa keepdims menghasilkan rata-rata berbentuk (3,), dan bentuk itu tidak dapat diselaraskan dengan (3, 4) karena NumPy membacanya sebagai vektor sepanjang sumbu terakhir. Dengan keepdims=True, rata-rata berbentuk (3, 1), sehingga setiap baris array asal dibagi dengan rata-rata barisnya sendiri dan hasilnya berbentuk (3, 4). Nilai 0,95 pada pojok kiri atas berasal dari 80 dibagi 84,5, yaitu rata-rata baris pertama. Penyelarasan bentuk semacam ini dibahas lebih rinci pada topik-topik broadcasting.
Penolakan pada pemanggilan pertama dapat dijelaskan dari arah penyelarasan bentuk. NumPy menyandingkan bentuk dari sumbu terakhir, sehingga array rata-rata berbentuk (3,) dibandingkan dengan sumbu terakhir array asal yang berpanjang 4, dan panjang 3 melawan 4 tidak dapat disatukan. Bentuk (3, 1) hasil keepdims lolos karena sumbu terakhirnya berpanjang 1, sehingga nilai tunggal pada setiap baris berlaku untuk seluruh kolom baris tersebut.
Operasi kumulatif cumsum dan cumprod#
Operasi kumulatif tidak meringkas array menjadi lebih kecil, melainkan menghasilkan array berbentuk sama dengan array asalnya. Fungsi np.cumsum menghitung penjumlahan berjalan, yaitu pada posisi ke-i disimpan jumlah seluruh elemen dari awal sampai posisi itu. Fungsi np.cumprod melakukan hal yang sama untuk perkalian.
import numpy as np
nilai = np.array([3, 1, 4, 1, 5])
print(np.cumsum(nilai))
print(np.cumprod(nilai))[ 3 4 8 9 14]
[ 3 3 12 12 60]Hasil cumsum berbunyi 3, lalu 3 + 1 = 4, lalu 4 + 4 = 8, dan seterusnya sampai 14, sedangkan hasil cumprod mengalikan secara berjalan sampai 60. Panjang hasil sama dengan panjang asalnya, yaitu lima elemen, berbeda dengan np.sum yang menghasilkan satu bilangan saja.
Pola kumulatif muncul ketika perkembangan nilai lebih penting daripada total akhirnya. Penjumlahan berjalan cocok untuk akumulasi bertahap, misalnya jumlah peserta yang mendaftar dari hari ke hari, sedangkan perkalian berjalan cocok untuk pertumbuhan berlipat, misalnya nilai tabungan yang ditambah bunga tetap setiap periode. Karena panjang hasilnya sama dengan data asalnya, deret kumulatif tersebut dapat langsung dipetakan sebagai grafik atau dibandingkan selisihnya dengan data asalnya.
Pada array dua dimensi, operasi kumulatif mengikuti semantik axis yang sama dengan fungsi reduksi. Sumbu yang disebut adalah arah berjalannya akumulasi.
import numpy as np
skor = np.array([[2, 3, 1], [1, 2, 2]])
print(np.cumsum(skor, axis=0))
print(np.cumsum(skor, axis=1))[[2 3 1]
[3 5 3]]
[[2 5 6]
[1 3 5]]Dengan axis=0, akumulasi berjalan dari baris ke baris, sehingga baris kedua memuat jumlah baris pertama dan baris kedua. Dengan axis=1, akumulasi berjalan menyusuri kolom setiap baris, sehingga setiap sel memuat jumlah dari kolom pertama sampai posisinya. Kedua hasil tetap berbentuk (2, 3) seperti array asalnya.
Kesalahan umum#
Kesalahan pertama adalah menukar np.sum dengan np.cumsum karena keduanya sama-sama berkenaan dengan penjumlahan. Fungsi np.sum menghasilkan satu bilangan, sedangkan np.cumsum menghasilkan array berukuran sama dengan asalnya, sehingga kesalahan ini biasanya baru terasa ketika bentuk hasil tidak cocok dengan perhitungan lanjutan.
import numpy as np
nilai = np.array([3, 1, 4, 1, 5])
print(np.sum(nilai))
print(np.cumsum(nilai))14
[ 3 4 8 9 14]Baris pertama adalah total seluruh elemen, sedangkan baris kedua adalah deretan penjumlahan berjalan. Apabila yang dibutuhkan hanya total, gunakan np.sum, dan gunakan np.cumsum apabila perkembangan nilainya dari waktu ke waktu memang ingin dipertahankan, misalnya untuk mencatat total antrean yang bertambah setiap jam.
Kesalahan kedua adalah menganggap keepdims=True mengubah isi hasil. Parameter tersebut hanya menambahkan sumbu berpanjang 1, dan nilainya tetap identik dengan hasil tanpa keepdims. Perbaikannya adalah membaca shape kedua hasil dan membandingkan isinya, sebagaimana ditunjukkan pada bagian pertama topik ini, lalu memilih bentuk yang dibutuhkan oleh operasi berikutnya. Pemeriksaan shape sebelum dan sesudah agregasi merupakan kebiasaan yang mencegah kebingungan semacam ini.
Ringkasan#
keepdims=Truemempertahankan sumbu yang diringkas dengan panjang 1, sehingga(3, 4)denganaxis=0menghasilkan(1, 4)alih-alih(4,).- Bentuk dengan sumbu berpanjang 1 memudahkan penyelarasan terhadap array asal pada operasi broadcasting, misalnya pembagian setiap baris dengan rata-rata barisnya.
np.cumsumdannp.cumprodmenghasilkan array berbentuk sama dengan asalnya, berisi penjumlahan dan perkalian berjalan.- Pada array dua dimensi, kumulatif mengikuti semantik
axisyang sama dengan fungsi reduksi, yaitu sumbu yang disebut adalah arah berjalannya akumulasi.
Referensi#
- numpy.sum — NumPy
— Dokumentasi resmi parameter
keepdimsdan bentuk hasilnya. - numpy.cumsum — NumPy — Dokumentasi resmi penjumlahan berjalan, termasuk perilaku per sumbu.
- numpy.cumprod — NumPy — Dokumentasi resmi perkalian berjalan pada array.
- Broadcasting — NumPy
— Panduan resmi aturan penyelarasan bentuk yang menjadi latar kegunaan
keepdims.