Module statistics dari chapter sebelumnya menghitung dengan benar, tetapi list Python punya batas struktural: elemennya tersebar di memori dan setiap operasi memproses satu per satu lewat loop. Data nyata jarang sekecil sepuluh angka — nilai lintas kelas, harga harian, hasil sensus semuanya berbentuk tabel besar. NumPy mengganti list dengan array: satu blok memori berisi data bertipe seragam, sehingga operasi statistik dapat dijalankan sekali panggil untuk seluruh data. Chapter ini membangun kebiasaan bekerja dengan array, memetakan function inti, membongkar satu jebakan penting bernama ddof, lalu menutup dengan skrip ringkasan yang menghitung statistik per baris dan per kolom.

Dari List ke Array #

np.array(list) mengubah list Python menjadi array NumPy. Perbedaan praktis pertama terasa saat menghitung mean — bandingkan loop manual dengan pemanggilan function:

python
import numpy as np

nilai = [68, 75, 75, 81, 84, 88, 90, 92, 97, 70]
arr = np.array(nilai)

total = 0
for x in nilai:
    total += x
print("mean lewat loop :", total / len(nilai))
print("np.mean(arr)    :", np.mean(arr))
print("arr.mean()      :", arr.mean())
print("tipe elemen     :", arr.dtype)

Output yang Dihasilkan:

text
mean lewat loop : 82.0
np.mean(arr)    : 82.0
arr.mean()      : 82.0
tipe elemen     : int64

Ketiga jalur menghasilkan mean yang sama, 82.0. Loop menghitung jumlah satu per satu lalu membagi 10; np.mean(arr) dan arr.mean() memakai mesin NumPy yang memproses seluruh blok data sekaligus — pola ini disebut vektorisasi. Gaya NumPy juga berlaku untuk operasi aritmetika: arr + 5 menghasilkan array baru yang seluruh elemennya bertambah 5 tanpa satu baris loop pun. Untuk data kecil perbedaannya tak terasa, tetapi pada data besar vektorisasi berjalan di kode terkompilasi sehingga konsep kerjanya jauh lebih efisien daripada loop Python per elemen. Attribute dtype melaporkan tipe elemen array — int64 untuk data bulat pada komputer 64-bit.

Statistik Inti: median, range, dan percentile #

Function inti NumPy memetakan konsep Section Statistika Deskriptif satu per satu. np.ptp menghitung range (peak to peak = maksimum − minimum), dan np.percentile menjadi perhatian khusus karena default metodenya:

python
import numpy as np
import statistics

nilai = [68, 75, 75, 81, 84, 88, 90, 92, 97, 70]
arr = np.array(nilai)

print("median              :", np.median(arr))
print("range (np.ptp)      :", np.ptp(arr))
print("min / max           :", np.min(arr), "/", np.max(arr))
print("percentile 25/50/75 :", np.percentile(arr, [25, 50, 75]))
print("quantiles inclusive :", statistics.quantiles(nilai, n=4, method="inclusive"))

Output yang Dihasilkan:

text
median              : 82.5
range (np.ptp)      : 29
min / max           : 68 / 97
percentile 25/50/75 : [75.  82.5 89.5]
quantiles inclusive : [75.0, 82.5, 89.5]

Median 82.5, range 29 (dari 97 − 68), dan min/max 68/97 — semuanya konsisten dengan hitungan chapter sebelumnya. Baris terakhir adalah temuan penting: np.percentile dengan metode default linear menghasilkan 75, 82.5, 89.5 — angka yang persis sama dengan statistics.quantiles metode inclusive dari chapter Statistik dengan Python Standar. Hanya wadahnya berbeda: NumPy mengembalikan array, module statistics mengembalikan list. Function np.quantile adalah alias np.percentile dengan skala 0 sampai 1 (np.quantile(arr, 0.25) sama dengan np.percentile(arr, 25)).

ddof: Populasi atau Sampel #

Satu perbedaan antar pustaka ini paling sering menjebak pendatang baru. statistics.stdev dari chapter sebelumnya membagi dengan n − 1 (versi sampel) secara default. NumPy memilih kebalikannya: np.var dan np.std membagi dengan n (versi populasi) kecuali parameter ddof diubah:

python
import numpy as np
import statistics

nilai = [68, 75, 75, 81, 84, 88, 90, 92, 97, 70]
arr = np.array(nilai)

print("np.var default :", np.var(arr))
print("np.var ddof=1  :", np.var(arr, ddof=1))
print("pvariance      :", statistics.pvariance(nilai))
print("variance       :", statistics.variance(nilai))
print("np.std default :", np.std(arr))
print("np.std ddof=1  :", np.std(arr, ddof=1))

Output yang Dihasilkan:

text
np.var default : 86.8
np.var ddof=1  : 96.44444444444444
pvariance      : 86.8
variance       : 96.44444444444444
np.std default : 9.316651759081692
np.std ddof=1  : 9.820613241770824

Empat baris pertama menegaskan pemetaannya: np.var(arr) default sama dengan pvariance (86.8), dan np.var(arr, ddof=1) sama dengan variance (96.44). Nama ddof berarti delta degrees of freedom — berapa derajat kebebasan dikurangi dari pembagi n; ddof=1 memindahkan pembagi ke n − 1, persis logika sampel versus populasi dari chapter Varians dan Standar Deviasi. Standar deviasi mengikuti variansinya: np.std(arr) 9.3167 melawan np.std(arr, ddof=1) 9.8206.

Korelasi dan Data Hilang #

Untuk korelasi, NumPy memakai bentuk matriks. np.corrcoef(x, y) mengembalikan tabel 2 × 2 yang perlu dibaca dengan aturan sederhana:

python
import numpy as np

matematika = np.array([68, 75, 75, 81, 84, 88, 90, 92, 97, 70])
bahasa = np.array([70, 78, 74, 79, 85, 82, 88, 90, 94, 72])

matriks = np.corrcoef(matematika, bahasa)
print(matriks)
print("r =", round(float(matriks[0, 1]), 4))
print()
himpun = np.array([68, 75, np.nan, 81])
print("mean    :", np.mean(himpun))
print("nanmean :", round(float(np.nanmean(himpun)), 4))

Output yang Dihasilkan:

text
[[1.         0.97139345]
 [0.97139345 1.        ]]
r = 0.9714

mean    : nan
nanmean : 74.6667

Matriks korelasi selalu simetris: diagonalnya (korelasi variabel dengan dirinya sendiri) pasti 1, dan nilai r duduk di luar diagonal — matriks[0, 1] atau matriks[1, 0], keduanya 0.9714, angka yang identik dengan statistics.correlation dari chapter sebelumnya. Bagian kedua blok menghadapi masalah yang sering muncul pada data nyata: satu nilai hilang ditulis sebagai np.nan. Function np.mean menularkan nan ke hasilnya, sedangkan np.nanmean mengabaikan nilai hilang dan merata-ratakan sisanya — (68 + 75 + 81) / 3 = 74.6667. Keluarga nan-aware NumPy (nanmedian, nanstd, nanpercentile) mengikuti pola yang sama; strategi menangani data hilang secara utuh dibahas pada chapter Analisis Data dengan pandas.

Axis: Statistik per Baris dan Kolom #

Kekuatan sesungguhnya array muncul pada data dua dimensi. Array berikut menyimpan nilai empat siswa untuk tiga kelas — tiap baris satu kelas, tiap kolom satu posisi siswa:

text
[[75, 80, 85, 90],    baris 0 : kelas A
 [60, 70, 65, 75],    baris 1 : kelas B
 [88, 92, 79, 95]]    baris 2 : kelas C

Parameter axis mengarahkan statistik ke satu arah: axis=1 menjumlahkan menyusuri baris sehingga menghasilkan satu nilai per kelas (mean kelas A 82.5, kelas B 67.5, kelas C 88.5), sedangkan axis=0 menjumlahkan menuruni kolom sehingga menghasilkan satu nilai per posisi siswa (74.33, 80.67, 76.33, 86.67). Tanpa axis, mean() merata-ratakan seluruh dua belas angka menjadi 79.5. Demo lengkapnya berada di skrip di bawah — aturan menghafalnya: axis=1 merapatkan kolom (hasil per baris), axis=0 merapatkan baris (hasil per kolom).

Skrip Lengkap: statistik_numpy.py #

Skrip berikut merangkai seluruh materi chapter menjadi satu file. Simpan sebagai statistik_numpy.py, lalu jalankan dengan python3 statistik_numpy.py:

python statistik_numpy.py
import numpy as np

nilai = np.array([68, 75, 75, 81, 84, 88, 90, 92, 97, 70])

print("== Ringkasan 10 nilai Matematika ==")
print(f"mean   : {nilai.mean()}")
print(f"median : {np.median(nilai)}")
print(f"range  : {np.ptp(nilai)}")
print(f"std s  : {np.std(nilai, ddof=1):.4f}")
print(f"std p  : {np.std(nilai):.4f}")

kelas = np.array([
    [75, 80, 85, 90],
    [60, 70, 65, 75],
    [88, 92, 79, 95],
])

print()
print("== Array 2D: 3 kelas x 4 siswa ==")
print(f"mean seluruh data : {kelas.mean()}")
print(f"mean per baris    : {kelas.mean(axis=1)}")
print(f"mean per kolom    : {kelas.mean(axis=0).round(2)}")

Output yang Dihasilkan:

text
== Ringkasan 10 nilai Matematika ==
mean   : 82.0
median : 82.5
range  : 29
std s  : 9.8206
std p  : 9.3167

== Array 2D: 3 kelas x 4 siswa ==
mean seluruh data : 79.5
mean per baris    : [82.5 67.5 88.5]
mean per kolom    : [74.33 80.67 76.33 86.67]

Lima baris pertama menyarikan dataset sepuluh siswa dengan kedua versi standar deviasi — ddof=1 untuk sampel, default untuk populasi. Bagian kedua memindahkan hitungan ke array 2D: mean seluruh data 79.5, lalu axis=1 menghasilkan array tiga nilai (satu per kelas) dan axis=0 menghasilkan array empat nilai (satu per posisi siswa), dengan .round(2) menjaga tampilan tetap ringkas. Array adalah mesin hitung, tetapi kolomnya tanpa nama dan barisnya tanpa identitas — data berlabel seperti nama siswa dan kelas membutuhkan struktur yang lebih kaya. pandas membangun struktur itu tepat di atas array NumPy, dan chapter Analisis Data dengan pandas melanjutkan di sana.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

statistik_numpy.py

Unduh berkas
python
import numpy as np

nilai = np.array([68, 75, 75, 81, 84, 88, 90, 92, 97, 70])

print("== Ringkasan 10 nilai Matematika ==")
print(f"mean   : {nilai.mean()}")
print(f"median : {np.median(nilai)}")
print(f"range  : {np.ptp(nilai)}")
print(f"std s  : {np.std(nilai, ddof=1):.4f}")
print(f"std p  : {np.std(nilai):.4f}")

kelas = np.array([
    [75, 80, 85, 90],
    [60, 70, 65, 75],
    [88, 92, 79, 95],
])

print()
print("== Array 2D: 3 kelas x 4 siswa ==")
print(f"mean seluruh data : {kelas.mean()}")
print(f"mean per baris    : {kelas.mean(axis=1)}")
print(f"mean per kolom    : {kelas.mean(axis=0).round(2)}")