Idenya
Agregasi mengubah banyak angka menjadi lebih sedikit: total, rata-rata, maksimum. Pada array 1-D hasilnya satu angka. Pada grid 2-D kamu punya pilihan: rangkum semuanya, setiap baris, atau setiap kolom. Argumen axis menentukan pilihan itu, dan begitu kamu paham, satu keluarga pertanyaan menjadi satu baris pendek.
import numpy as np
stores = ["Jakarta", "Bandung", "Surabaya", "Medan"]
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
units = np.array([
[120, 135, 150, 160, 155, 170],
[ 80, 85, 90, 88, 95, 100],
[ 95, 92, 105, 110, 108, 115],
[ 40, 45, 43, 50, 52, 55],
])
Seluruh array
Mulai dari kasus paling sederhana, merangkum setiap angka di grid. Berapa total unit yang dijual keempat toko selama enam bulan, dan berapa angka bulanan terkecil dan terbesar dari toko mana pun?
print(units.sum(), units.mean(), units.min(), units.max())
print(units.std().round(1))
2338 97.41666666666667 40 170
37.4
Setiap method punya kembaran berbentuk fungsi: units.sum() sama dengan np.sum(units). Beberapa yang berguna hanya ada sebagai fungsi, seperti np.median dan np.percentile:
print(np.median(units), np.percentile(units, 90))
95.0 153.5
Argumen axis
axis menyatakan dimensi mana yang diremas:
axis=0meremas baris (turun di setiap kolom): satu hasil per kolom, di sini per bulan.axis=1meremas kolom (melintang di setiap baris): satu hasil per baris, di sini per toko.
print(units.sum(axis=0)) # total per bulan
print(units.sum(axis=1)) # total per toko
[335 357 388 408 410 440]
[890 538 625 285]
axis=0 ↓ (turun melewati baris, hasil per kolom). axis=1 → (melintang melewati kolom, hasil per baris). Axis yang kamu sebut adalah yang menghilang: (4, 6) yang dijumlahkan atas axis 0 menjadi (6,); atas axis 1 menjadi (4,).
Setiap agregasi menerima axis:
print(units.mean(axis=1).round(1)) # rata-rata bulan per toko
print(units.max(axis=0)) # unit toko terbaik di setiap bulan
[148.3 89.7 104.2 47.5]
[120 135 150 160 155 170]
Di mana maksimumnya? argmax dan argmin
.max() memberi nilai terbesar; .argmax() memberi posisinya. Digabung dengan list labelmu, itu menjawab "yang mana?":
print(units.argmax(axis=1)) # posisi bulan terbaik setiap toko
weakest = units.argmin(axis=1) # posisi bulan terlemah setiap toko
for store, m in zip(stores, weakest):
print(f"{store}: weakest month {months[m]}")
[5 5 5 5]
Jakarta: weakest month Jan
Bandung: weakest month Jan
Surabaya: weakest month Feb
Medan: weakest month Jan
Setiap toko mencapai puncaknya di bulan Juni (posisi 5), tanda pertumbuhan yang stabil. Bulan terlemah mereka berbeda-beda. Loop di sini hanya memformat output; perhitungannya sendiri adalah satu pemanggilan tervektorisasi. Kamu bahkan bisa melewatkan loop-nya dengan fancy indexing: np.array(months)[weakest].
Porsi dari total: keepdims
Berapa porsi yang disumbangkan setiap bulan terhadap setengah tahun setiap toko? Bagi setiap baris dengan totalnya sendiri. Tapi units.sum(axis=1) ber-shape (4,), yang tidak bisa di-broadcast terhadap (4, 6) per baris (kamu sudah melihat error itu di modul sebelumnya). keepdims=True mempertahankan axis yang diremas dengan ukuran 1:
totals = units.sum(axis=1, keepdims=True)
print(totals.shape)
share = units / totals
print((share * 100).round(1))
(4, 1)
[[13.5 15.2 16.9 18. 17.4 19.1]
[14.9 15.8 16.7 16.4 17.7 18.6]
[15.2 14.7 16.8 17.6 17.3 18.4]
[14. 15.8 15.1 17.5 18.2 19.3]]
Dengan shape (4, 1), total-nya di-broadcast ke setiap baris. Setiap baris sekarang berjumlah 100%.
Total berjalan: cumsum
cumsum memberi total berjalan di sepanjang sebuah axis, versi NumPy dari kolom kumulatif di Excel:
cumulative = units.cumsum(axis=1)
print(cumulative)
[[120 255 405 565 720 890]
[ 80 165 255 343 438 538]
[ 95 187 292 402 510 625]
[ 40 85 128 178 230 285]]
Gabungkan dengan mask dan argmax untuk menjawab "di bulan apa setiap toko melewati 400 unit?":
passed = cumulative >= 400
print(passed.argmax(axis=1))
[2 4 3 0]
argmax pada boolean mengembalikan posisi True yang pertama. Hati-hati: kalau sebuah baris sama sekali tidak punya True (Medan tidak pernah mencapai 400 di rentang ini), argmax mengembalikan 0, yang terlihat seperti "Januari". Periksa dengan passed.any(axis=1) sebelum memercayai jawabannya:
print(passed.any(axis=1))
[ True True True False]
Nilai yang hilang: fungsi yang sadar nan
Data sungguhan punya celah. Pelanggan yang tidak memberi rating tidak punya rating, dan NumPy mewakilinya dengan np.nan, yang berarti "bukan angka". Masalahnya, nan menular: perhitungan biasa apa pun yang menyentuhnya ikut menjadi nan, jadi satu rating yang hilang merusak rata-ratanya:
ratings = np.array([4.5, 5.0, np.nan, 3.5, 4.0])
print(ratings.mean())
print(np.nanmean(ratings), np.nansum(ratings), np.nanmax(ratings))
nan
4.25 17.0 5.0
np.nanmean, np.nansum, np.nanmax dan kawan-kawannya melewati nilai yang hilang, seperti AVG di SQL dan .mean() default di pandas.
Mengapa ini penting untuk kode yang bersih
units.sum(axis=1) menggantikan loop yang membangun list total, dan menyatakan dengan tepat apa yang dihitungnya: total per toko. Beri nama hasilnya sesuai isinya (store_totals, best_month), pakai keepdims=True saat kamu akan membagi dengannya, dan lindungi argmax pada mask dengan .any(). Kebiasaan kecil ini mencegah jawaban salah yang senyap, yang paling sulit ditangkap.
Rangkuman
.sum(),.mean(),.min(),.max(),.std(),np.median,np.percentilemerangkum array.axis=0memberi satu hasil per kolom;axis=1satu per baris. Axis yang disebut menghilang..argmax()/.argmin()memberi posisi nilai ekstrem.keepdims=Truemembuat shape siap di-broadcast, misalnya untuk porsi dari total baris..cumsum(axis=...)memberi total berjalan;argmaxpada mask menemukanTruepertama (periksa.any()).np.nanmean,np.nansum... mengabaikannan.