Section Variabel Acak dan Distribusi menghitung setiap peluang dengan tangan: tabel PMF disusun baris demi baris, luas kurva normal dibaca lewat standarisasi z, ekor t dihitung dari tabel. Semua hitungan itu benar, tetapi tidak praktis untuk kasus ratusan nilai atau parameter yang berubah-ubah. Modul scipy.stats mengubah perhitungan tersebut menjadi panggilan satu baris: setiap distribusi adalah objek dengan metode yang seragam. Chapter ini menjalankan ulang tabel-tabel dari section teori — binomial, Poisson, normal, dan t-Student — memverifikasi bahwa SciPy menghasilkan angka yang sama, lalu menambah dua kemampuan yang tidak dimiliki tabel cetak: kuantil terbalik dan sampel acak yang dapat direproduksi.

Objek Distribusi sebagai Kalkulator #

from scipy.stats import binom memuat objek distribusi binomial — bukan sekadar kumpulan fungsi, melainkan satu entitas yang tahu parameternya sendiri dan menerima pertanyaan dalam berbagai bentuk. Metode-metodenya seragam untuk seluruh keluarga distribusi:

MetodePertanyaan yang dijawabBerlaku untuk
pmf(k)P(X = k) — peluang titikdistribusi diskret
cdf(x)P(X ≤ x) — peluang kumulatifsemua
sf(x)P(X > x) — peluang ekor kanansemua
ppf(q)nilai x dengan P(X ≤ x) = qsemua
rvs()sampel acak dari distribusisemua
mean(), var()parameter ringkassemua

Konvensi parameternya perlu dihafal dua saja. Distribusi diskret menerima data lebih dulu: binom.pmf(k, n, p) dan poisson.pmf(k, mu) — nilai k di depan, parameter menyusul. Distribusi kontinu memakai loc dan scale: norm.cdf(x, loc=mu, scale=sigma) — dan karena loc menggeser pusat serta scale mengatur lebar, normal baku cukup ditulis norm.cdf(x) tanpa parameter. Untuk t-Student, derajat kebebasan selalu menjadi argumen: t.sf(2, df=15).

Binomial dan Poisson: Tabel yang Sama #

Tabel PMF lima lemparan koin — X ~ B(5, 0.5) — dulu dihitung dari kombinasi pecahan 1/32 sampai 10/32. Blok berikut menghitungnya dua kali: sekali dengan binom.pmf, sekali dengan rumus manual math.comb(5, k) × 0.5^5, lalu tabel Poisson λ = 2 untuk cacat per batch mengikuti di bawahnya.

python
import math
from scipy.stats import binom, poisson

print("binomial n = 5, p = 0.5")
print(f"{'k':>3} {'scipy':>8} {'manual':>8}")
for k in range(6):
    pmf = binom.pmf(k, 5, 0.5)
    manual = math.comb(5, k) * 0.5**5
    print(f"{k:>3} {pmf:>8.4f} {manual:>8.4f}")

print("poisson lambda = 2")
print(f"{'k':>3} {'P(X = k)':>9}")
for k in range(7):
    print(f"{k:>3} {poisson.pmf(k, 2):>9.4f}")

Output yang Dihasilkan:

text
binomial n = 5, p = 0.5
  k    scipy   manual
  0   0.0312   0.0312
  1   0.1562   0.1562
  2   0.3125   0.3125
  3   0.3125   0.3125
  4   0.1562   0.1562
  5   0.0312   0.0312
poisson lambda = 2
  k  P(X = k)
  0    0.1353
  1    0.2707
  2    0.2707
  3    0.1804
  4    0.0902
  5    0.0361
  6    0.0120

Kolom scipy dan kolom manual identik pada seluruh baris — SciPy mengevaluasi rumus yang sama persis, C(n, k) · p^k · (1−p)^(n−k), tanpa pembulatan antara sehingga hasilnya stabil pada empat desimal. Angka-angkanya juga cocok baris demi baris dengan tabel pada chapter Distribusi Binomial: puncak kembar 0.3125 pada k = 2 dan k = 3, simetri sempurna k = 0 dengan k = 5. Tabel Poisson λ = 2 sama persis dengan chapter Distribusi Poisson — dua puncak 0.2707 pada k = 1 dan k = 2 mengapit λ, lalu menurun cepat ke 0.0120 pada k = 6. Ketika rumus manual dan pustaka sepakat seperti ini, pustaka layak dipercaya untuk parameter yang lebih rumit — misalnya Poisson(12) yang tidak lagi manusiawi dihitung dengan tangan.

Normal dan t: cdf, ppf, dan Distribusi Beku #

Distribusi normal menyatukan dua arah perhitungan. Arah pertama, dari nilai ke peluang: norm.cdf(1.96) menghasilkan 0.9750 — angka yang chapter Distribusi Normal kita baca dari tabel z. Arah kedua, dari peluang ke nilai: norm.ppf(0.975) mengembalikan 1.9600 — ppf adalah kuantil terbalik, cermin dari cdf. Pola panggilan berulang pada parameter yang sama dapat dirapikan dengan distribusi beku (frozen): norm(loc=168, scale=7) mengembalikan objek yang parameternya sudah terpasang, sehingga pertanyaan tinggi badan cukup ditujukan ke objek itu.

python
from scipy.stats import norm, t

print(f"P(Z <= 1.96) = {norm.cdf(1.96):.4f}")
print(f"ppf(0.975)   = {norm.ppf(0.975):.4f}")

tinggi = norm(loc=168, scale=7)   # distribusi beku: parameter terpasang
print(f"P(X <= 175)  = {tinggi.cdf(175):.4f}")
print(f"P(X > 180)   = {tinggi.sf(180):.4f}")
print(f"ppf(0.90)    = {tinggi.ppf(0.90):.2f} cm")

print(f"{'df':>6} {'P(T > 2)':>9}")
for df in (1, 5, 10, 30):
    print(f"{df:>6} {t.sf(2, df):>9.4f}")
print(f"{'normal':>6} {norm.sf(2):>9.4f}")
print(f"P(T > 2, df = 15) = {t.sf(2, 15):.4f}")

Output yang Dihasilkan:

text
P(Z <= 1.96) = 0.9750
ppf(0.975)   = 1.9600
P(X <= 175)  = 0.8413
P(X > 180)   = 0.0432
ppf(0.90)    = 176.97 cm
    df  P(T > 2)
     1    0.1476
     5    0.0510
    10    0.0367
    30    0.0273
normal    0.0228
P(T > 2, df = 15) = 0.0320

Tiga angka contoh tinggi badan — P(X ≤ 175) = 0.8413, P(X > 180) = 0.0432, hingga persentil ke-90 sebesar 176.97 cm — identik dengan perhitungan standarisasi z pada chapter Distribusi Normal; distribusi beku hanya merapikan kode, bukan mengubah hasil. Tabel ekor t memperlihatkan perilaku yang dibahas chapter Distribusi t-Student: pada df = 1 peluang melewati 2 mencapai 0.1476 — hampir tujuh kali lipat normal — lalu menipis bertahap menuju 0.0228 milik normal ketika df = 30. Baris terakhir, P(T > 2; df = 15) = 0.0320, adalah contoh 16 siswa dari chapter yang sama. Seluruh tabel yang dulu dihitung manual kini direproduksi dengan satu loop pendek.

Sampel Acak yang Dapat Direproduksi #

Metode rvs mengambil sampel acak dari distribusi — kemampuan yang tidak dimiliki tabel cetak dan menjadi pintu masuk simulasi. Masalahnya segera terasa: hasil acak berbeda pada setiap eksekusi, sehingga analisis yang memuatnya tidak dapat diverifikasi ulang. Solusinya adalah seed: rvs menerima parameter random_state, dan generator np.random.default_rng(42) yang sama menjamin aliran acak yang sama.

python
import numpy as np
from scipy.stats import norm

rng = np.random.default_rng(42)
sampel1 = norm.rvs(loc=168, scale=7, size=3, random_state=rng)
sampel2 = norm.rvs(loc=168, scale=7, size=3, random_state=rng)

rng = np.random.default_rng(42)   # seed yang sama diulang dari awal
sampel3 = norm.rvs(loc=168, scale=7, size=3, random_state=rng)

print("sampel1 :", [f"{v:.2f}" for v in sampel1])
print("sampel2 :", [f"{v:.2f}" for v in sampel2])
print("sampel3 :", [f"{v:.2f}" for v in sampel3])
print("sampel1 sama dengan sampel3 :", bool(np.allclose(sampel1, sampel3)))

Output yang Dihasilkan:

text
sampel1 : ['170.13', '160.72', '173.25']
sampel2 : ['174.58', '154.34', '158.88']
sampel3 : ['170.13', '160.72', '173.25']
sampel1 sama dengan sampel3 : True

Perilakunya perlu dibaca hati-hati. sampel1 dan sampel2 berbeda meski memakai generator yang sama — generator menyimpan posisi internalnya, dan tiap pengambilan mendorong posisi itu maju, persis seperti kartu yang terus dibagikan dari satu dek. Baris rng = np.random.default_rng(42) membuat generator baru dari seed awal, sehingga sampel3 jatuh pada angka yang sama dengan sampel1 — komparasi np.allclose mengonfirmasinya dengan True. Determinisme semacam ini adalah syarat praktik analisis yang bisa direproduksi: setiap laporan yang memuat hasil acak wajib mencatat seed yang dipakainya.

Skrip Terpadu: distribusi_lengkap.py #

Tiga distribusi inti dirangkai menjadi satu skrip yang dapat dijalankan ulang — setiap angkanya mengambil jalan berbeda (PMF, CDF, kuantil) namun semuanya sudah diverifikasi pada chapter teorinya masing-masing.

"""distribusi_lengkap.py — tiga distribusi inti dalam satu skrip."""

from scipy.stats import binom, poisson, norm

print(f"binomial : P(X = 2) = {binom.pmf(2, 5, 0.5):.4f} (puncak bersama k = 3)")  # 5 lemparan koin
print(f"poisson  : P(X <= 2) = {poisson.cdf(2, 3):.4f}")  # call center: 3 panggilan per jam

tinggi = norm(loc=168, scale=7)  # tinggi badan: mu = 168 cm, sigma = 7 cm
print(f"normal   : P(X <= 175) = {tinggi.cdf(175):.4f}")
print(f"normal   : persentil ke-90 = {tinggi.ppf(0.90):.2f} cm")

Output yang Dihasilkan:

text
binomial : P(X = 2) = 0.3125 (puncak bersama k = 3)
poisson  : P(X <= 2) = 0.4232
normal   : P(X <= 175) = 0.8413
normal   : persentil ke-90 = 176.97 cm

Skrip ini memakai tiga pintu masuk yang berbeda pada objek distribusi: binom.pmf untuk peluang titik, poisson.cdf untuk peluang kumulatif — P(X ≤ 2) = 0.4232 pada λ = 3, persis contoh call center chapter Distribusi Poisson — dan kombinasi cdf dengan ppf pada distribusi beku tinggi badan. Perhatikan bahwa skrip tidak mengimpor apa pun selain tiga objek distribusi: seluruh mesin peluang tersedia tanpa konfigurasi tambahan. Antarmuka lengkap seluruh keluarga distribusi terdokumentasi di dokumentasi scipy.stats , sedangkan sifat-sifat tiap distribusi dirangkum dalam NIST Engineering Statistics Handbook .

Tabel dan kuantil kini tinggal dipanggil, tetapi statistika jarang berhenti di menghitung peluang — langkah berikutnya adalah mengambil keputusan dari angka itu. Chapter berikutnya membawa tabel-tabel distribusi ini ke kerangka lima langkah pengujian hipotesis: scipy.stats menyediakan uji t, chi-square, ANOVA, dan korelasi siap pakai yang menghasilkan statistik uji serta p-value dalam satu panggilan.

Berkas Sumber

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

distribusi_lengkap.py

Unduh berkas
python
"""distribusi_lengkap.py — tiga distribusi inti dalam satu skrip."""

from scipy.stats import binom, poisson, norm

print(f"binomial : P(X = 2) = {binom.pmf(2, 5, 0.5):.4f} (puncak bersama k = 3)")  # 5 lemparan koin
print(f"poisson  : P(X <= 2) = {poisson.cdf(2, 3):.4f}")  # call center: 3 panggilan per jam

tinggi = norm(loc=168, scale=7)  # tinggi badan: mu = 168 cm, sigma = 7 cm
print(f"normal   : P(X <= 175) = {tinggi.cdf(175):.4f}")
print(f"normal   : persentil ke-90 = {tinggi.ppf(0.90):.2f} cm")