Setiap standard error pada section ini lahir dari rumus, dan setiap rumus membawa syarat: s/√n mengandaikan data menyebar kira-kira lonceng, SE proporsi mengandaikan percobaan Bernoulli, SE selisih dua mean mengandaikan kedua kelompok normal. Chapter Galat Standar Robust baru saja memperlihatkan akibatnya ketika syarat dilanggar — s ikut membengkak, dan SE yang dihasilkan mengukur pencilan alih-alih sebaran. Sekarang kita ajukan pertanyaan yang lebih berani: bisakah standard error diukur langsung dari data, tanpa rumus dan tanpa syarat bentuk sebaran? Bootstrap resampling menjawab ya: perlakukan sampel sebagai populasi, lalu tiru proses pengambilan sampel berkali-kali. Metode ini diperkenalkan oleh Bradley Efron pada 1979, dan kekuatannya paling terasa justru pada statistik tanpa rumus SE — median, trimmed mean, atau korelasi.
Ide Besar: Sampel Menjadi Populasi #
Chapter Distribusi Sampling bisa menghitung distribusi sampling mean secara eksak karena populasinya mini: enam siswa, dan seluruh 15 sampel berukuran 2 dihitung satu per satu. Pada data nyata, populasi tidak diketahui dan enumerasi mustahil — di titik itu bootstrap mengambil alih.
Idenya disebut plug-in: ganti distribusi populasi yang tidak diketahui dengan distribusi empiris — data yang kita pegang, dengan tiap observasi berpeluang sama 1/n. Dari “populasi” tiruan ini, ambil n nilai secara acak dengan penggantian, hitung statistiknya, catat hasilnya. Ulangi B kali. B nilai statistik itu menjadi gambaran distribusi sampling sebagaimana dipandang oleh data: sebarannya meniru sebaran yang akan muncul bila proses pengambilan sampel benar-benar diulang berkali-kali.
Batas metode ini perlu dinyatakan sejak awal. Bootstrap tidak memulihkan distribusi sampling yang sesungguhnya; bootstrap meniru distribusi sampling pada populasi yang persis sama dengan sampel Anda. Sampel yang baik menghasilkan tiruan yang baik; sampel yang tidak mewakili menghasilkan tiruan yang meyakinkan dari hal yang keliru — kekuatan komputasi tidak menggantikan kualitas pengambilan sampel.
Mekanika: Lima Langkah Bootstrap #
Seluruh mesin bootstrap berdiri di atas lima langkah yang sama untuk statistik apa pun:
1. Ambil n nilai dari data, DENGAN penggantian -> satu resampel
2. Hitung statistik pada resampel itu -> satu nilai
3. Ulangi langkah 1-2 sebanyak B kali -> B nilai
4. SE bootstrap = simpangan baku dari B nilai itu
5. CI persentil 95% = persentil ke-2.5 dan ke-97.5 dari B nilai ituDua detail pada langkah 1 menentukan segalanya. Pertama, undian dilakukan dengan penggantian: nilai yang sudah terundi kembali ke kolam dan berpeluang terundi lagi — itulah sebabnya satu resampel bisa memuat duplikat dan meninggalkan nilai lain. Kedua, ukuran resampel harus tepat n: undian tanpa penggantian hanya mengacak urutan data yang sama dan menghasilkan statistik identik setiap kali, sedangkan undian berukuran lain menjawab pertanyaan tentang ukuran sampel yang berbeda. Langkah 4 dan 5 lalu menerjemahkan B nilai menjadi dua barang yang selama ini dicari lewat rumus: standard error dan confidence interval.
Bootstrap Mean pada Data Sembilan Siswa #
Uji pertama sengaja memakai statistik yang rumusnya sudah kita kuasai, sehingga hasil bootstrap punya pembanding. Data sembilan siswa [68, 75, 75, 81, 84, 88, 90, 92, 97] (mean 83.33, s 9.41) menghasilkan SE rumus 3.1358 dan CI t 95% [76.10, 90.56] — angka-angka chapter Confidence Interval dan Standard Error. Blok berikut menjalankan B = 10.000 resampel dengan generator deterministik default_rng(42):
import numpy as np
import statistics
from scipy.stats import t
nilai = [68, 75, 75, 81, 84, 88, 90, 92, 97]
n = len(nilai)
s = statistics.stdev(nilai)
rng = np.random.default_rng(42)
B = 10000
indeks = rng.integers(0, n, size=(B, n))
resampel = np.array(nilai)[indeks]
pertama = resampel[0]
unik, jumlah = np.unique(pertama, return_counts=True)
print(f"resampel pertama : {pertama.tolist()}")
print(f"jumlah tiap nilai: {dict(zip(unik.tolist(), jumlah.tolist()))}")
mean_boot = resampel.mean(axis=1)
ci_boot = np.percentile(mean_boot, [2.5, 97.5])
tk = t.ppf(0.975, n - 1)
xbar = statistics.mean(nilai)
print(f"x-bar data : {xbar:.4f}")
print(f"SE rumus : {s / n**0.5:.4f}")
print(f"SE bootstrap : {mean_boot.std(ddof=1):.4f}")
print(f"CI persentil 95% : [{ci_boot[0]:.2f}, {ci_boot[1]:.2f}]")
print(f"CI t 95% : [{xbar - tk * s / n**0.5:.2f}, {xbar + tk * s / n**0.5:.2f}]")Output yang Dihasilkan:
resampel pertama : [68, 90, 88, 81, 81, 92, 68, 90, 75]
jumlah tiap nilai: {68: 2, 75: 1, 81: 2, 88: 1, 90: 2, 92: 1}
x-bar data : 83.3333
SE rumus : 3.1358
SE bootstrap : 2.9580
CI persentil 95% : [77.44, 89.00]
CI t 95% : [76.10, 90.56]Mari kita bedah kode di atas:
- Baris 9-12 (mesin resampling):
rng.integers(0, n, size=(B, n))mengundi indeks 0 sampai 8 sebanyak 9 × 10.000 dalam satu panggilan;np.array(nilai)[indeks]menerjemahkan seluruh indeks menjadi resampel — 10.000 baris, 9 kolom, tanpa satu pun perulangan eksplisit. - Baris 14-17 (resampel pertama): baris pertama resampel ditampilkan lengkap dengan jumlah tiap nilai lewat
np.unique(..., return_counts=True)— bukti kerja mekanisme penggantian. - Baris 19-27 (statistik):
resampel.mean(axis=1)merata-ratakan tiap baris menjadi 10.000 mean; simpangan bakunya (pembagi B − 1) adalah SE bootstrap, persentil 2.5 dan 97.5 membentuk CI, dan baris terakhir menghitung ulang CI t sebagai pembanding.
Resampel pertama [68, 90, 88, 81, 81, 92, 68, 90, 75] memperlihatkan penggantian sedang bekerja: nilai 68, 81, dan 90 masing-masing terundi dua kali, sedangkan 84 dan 97 tidak terundi sama sekali. Hasil utamanya: SE bootstrap 2.9580, dekat dengan SE rumus 3.1358. Kedekatan itu bukan kebetulan. Secara eksak, resampling dari sampel berukuran n memperlakukan varians populasi tiruan sebagai (n − 1)s²/n, sehingga SE bootstrap teoretisnya adalah s·√(n − 1)/n = 2.9565 — simulasi 10.000 resampel mendarat di 2.9580, dan selisih tipis itu murni derau simulasi. Rumus dan simulasi sepakat pada data bersih; bootstrap lulus uji pembandingnya.
CI persentil [77.44, 89.00] sedikit lebih sempit daripada CI t [76.10, 90.56]. Pada n = 9, metode persentil memang cenderung menghasilkan interval terlalu sempit: interval t membayar faktor kritis 2.306 (df = 8) untuk ketidakpastian menaksir σ, sedangkan persentil bootstrap tidak membayar apa pun. Untuk mean pada data bersih, rumus t tetap menjadi patokan — kekuatan bootstrap bukan di statistik yang sudah punya rumus.
Di Mana Bootstrap Bersinar: Median dan Trimmed Mean #
Untuk median tidak ada rumus plug-in yang bisa dibandingkan — dan di situ bootstrap bekerja tanpa pesaing. Kita jalankan pada data pendapatan tujuh pedagang dari chapter Galat Standar Robust (median 110, trimmed mean 20% = 110, mean 147.14), membandingkan tiga statistik sekaligus pada resampel yang sama:
import numpy as np
pendapatan = [80, 90, 100, 110, 120, 130, 400]
n = len(pendapatan)
rng = np.random.default_rng(42)
B = 10000
indeks = rng.integers(0, n, size=(B, n))
resampel = np.array(pendapatan)[indeks]
mean_boot = resampel.mean(axis=1)
median_boot = np.median(resampel, axis=1)
urut = np.sort(resampel, axis=1) # pangkas 1 nilai tiap ujung (trim 20%)
trim_boot = urut[:, 1:6].mean(axis=1)
for nama, boot in (("mean", mean_boot), ("median", median_boot), ("trim 20%", trim_boot)):
ci = np.percentile(boot, [2.5, 97.5])
print(f"{nama:9}: SE = {boot.std(ddof=1):6.2f}, CI 95% = [{ci[0]:6.2f}, {ci[1]:6.2f}]")
unik, jumlah = np.unique(median_boot, return_counts=True)
print(f"nilai berbeda median: {len(unik)}")
print(f"median = 400 terjadi : {jumlah[-1]} dari {B} resampel")Output yang Dihasilkan:
mean : SE = 39.23, CI 95% = [ 95.71, 234.29]
median : SE = 30.21, CI 95% = [ 90.00, 130.00]
trim 20% : SE = 38.27, CI 95% = [ 92.00, 230.00]
nilai berbeda median: 7
median = 400 terjadi : 93 dari 10000 resampelMari kita bedah kode di atas:
- Baris 9-14 (tiga statistik): mean dihitung per baris;
np.median(..., axis=1)mengambil median tiap resampel;np.sortmengurutkan tiap baris lalu irisan kolom 1 sampai 5 merata-ratakan lima nilai tengah — persis pangkasan satu nilai per ujung (trim 20%) dari chapter sebelumnya. - Baris 16-18 (laporan): satu perulangan mencetak SE dan CI persentil ketiga statistik dari kumpulan resampel yang sama.
- Baris 20-22 (kekasaran distribusi):
np.uniquepada 10.000 median menghitung ada berapa nilai berbeda; karenaunikterurut naik, elemen terakhirjumlah[-1]adalah frekuensi median 400.
Pembacaan pertama: SE median 30.21 lebih kecil daripada SE mean 39.23, dan CI median [90, 130] jauh lebih sempit daripada CI mean [95.71, 234.29]. Perlu diakui bahwa kedua interval menaksir parameter yang berbeda — CI mean bicara tentang μ yang memang tertarik ke ekor bila populasi memuat pedagang ekstrem, CI median bicara tentang pendapatan pedagang pada umumnya. Untuk pertanyaan “berapa pendapatan tipikal seorang pedagang”, median adalah parameter yang tepat, dan intervalnya informatif: antara 90 dan 130 ribu Rp.
Pembacaan kedua justru pelajaran yang tidak terduga: SE trimmed mean 38.27, nyaris sama besar dengan SE mean. Penyebabnya mekanis. Pangkasan 20% hanya membuang satu nilai per ujung, dan ketika nilai 400 terundi dua kali atau lebih dalam satu resampel — peluangnya 1 − (6/7)⁷ − (6/7)⁶ = 0.2635, lebih dari seperempat resampel — satu salinannya lolos ke tengah dan menarik trimmed mean ke atas. Pada data asli nilai 400 muncul sekali dan selalu terpangkas, tetapi proses pengambilan sampel ulang bisa mendatangkannya berlipat. Bootstrap dengan demikian juga berfungsi sebagai uji tekan bagi estimator: kelemahan yang tak terlihat pada satu sampel terlihat pada 10.000 resampel. Pelajaran praktisnya: persentase pangkasan harus melebihi tingkat kontaminasi yang dikhawatirkan — dan pada n = 7, median (pangkasan maksimal) adalah pilihan yang aman.
Distribusi bootstrap median juga layak dilihat apa adanya. Median resampel dari tujuh nilai hanya bisa jatuh pada tujuh kandidat — nilai data itu sendiri:
| Median resampel | Frekuensi | Persentase |
|---|---|---|
| 80 | 98 | 0.98% |
| 90 | 1012 | 10.12% |
| 100 | 2364 | 23.64% |
| 110 | 3085 | 30.85% |
| 120 | 2362 | 23.62% |
| 130 | 986 | 9.86% |
| 400 | 93 | 0.93% |
Sebarannya kasar — tujuh anak tangga, bukan kurva mulus — dan CI persentil [90, 130] otomatis berhenti pada nilai-nilai data. Median baru melompat ke 400 bila nilai itu terundi minimal empat kali dari tujuh undian, dan itu hanya terjadi pada 93 dari 10.000 resampel. Kekasaran seperti ini perlu dilaporkan apa adanya: interval yang tersusun dari tujuh kandidat memang hanya bisa setelit itu pada n = 7.
Aturan Praktik #
Empat kebiasaan menjaga bootstrap tetap sehat:
- B yang cukup. Untuk menaksir SE, B = 1.000 umumnya sudah stabil; untuk CI persentil, gunakan B = 10.000 karena persentil di ekor (2.5% dan 97.5%) membutuhkan resolusi yang lebih halus.
- Ukuran resampel tepat n. SE adalah properti statistik pada ukuran sampel tertentu; resampel berukuran 10 menjawab pertanyaan tentang n = 10, bukan n = 9.
- Selalu dengan penggantian. Tanpa penggantian, resampel hanyalah permutasi data yang sama: mean-nya identik di setiap resampel dan sebarannya nol — mesin kehilangan seluruh bahan ukurannya.
- Seed tetap untuk reproduktifitas.
default_rng(42)membuat seluruh angka pada chapter ini dapat dijalankan ulang dengan hasil identik — kebiasaan yang sama dengan seluruh blok Python pada course ini.
Batasan Bootstrap #
Sampel yang tidak mewakili. Bootstrap menirukan populasi dari sampel; bias pengambilan sampel terbawa utuh ke setiap resampel dan tidak dikoreksi oleh simulasi apa pun. Interval yang tampak meyakinkan tetap salah bila proses pengumpulan datanya bias sejak awal.
n kecil menghasilkan resolusi kasar. Tujuh kandidat median pada data pendapatan adalah contohnya: CI persentil hanya bisa mendarat pada nilai data, dan persentil 2.5/97.5 dari distribusi tujuh anak tangga memang tidak bisa lebih halus dari itu.
Data bergantung waktu. Observasi deret waktu yang berdekatan berkorelasi, sedangkan resampel acak memutus urutan hari — asumsi pertukaran antar observasi dilanggar. Skema khusus seperti block bootstrap, yang mengundi blok hari utuh agar struktur waktu terjaga, dibutuhkan; penerapannya menyusul pada Section Analisis Deret Waktu.
Metode interval yang lebih halus ada. Persentil adalah metode CI bootstrap paling sederhana. Varian BCa menyesuaikan kecondongan dan akselerasi sebaran; varian basic bekerja pada selisih statistik terhadap taksiran. Pada n besar ketiganya konvergen; pada n kecil perbedaannya terasa — persentil cenderung sempit, seperti perbandingan [77.44, 89.00] lawan [76.10, 90.56] pada data sembilan siswa.
Section Sampling dan Estimasi kini lengkap busurnya. Chapter Point Estimation memformalkan taksiran titik; Standard Error dan Confidence Interval memberi ukuran ketidakpastian lewat rumus; Menentukan Ukuran Sampel merencanakan presisi sebelum data terkumpul; dua chapter confidence interval lanjutan memperluasnya ke proporsi dan selisih dua mean; Galat Standar Robust menyiapkan penaksir yang tahan kontaminasi; dan bootstrap menutup dengan kemampuan mengukur ketidakpastian statistik apa pun tanpa rumus. Pola pikirnya bergeser dari “cari rumus yang sesuai” menjadi “definisikan statistik yang tepat untuk pertanyaan Anda, lalu taksir sebarannya dari data”.
Dengan taksiran dan ukuran ketidakpastian di tangan, pertanyaan berikutnya klasik: apakah efek yang terlihat cukup besar untuk dipercaya, atau masih wajar muncul karena kebetulan? Itu wilayah keputusan formal — Section Pengujian Hipotesis, termasuk chapter nonparametriknya (Mann-Whitney U Test, Wilcoxon Signed-Rank Test, Kruskal-Wallis Test) yang berbagi semangat sama dengan bootstrap: bekerja tetap andal ketika asumsi rumus klasik tidak terpenuhi. Rujukan lanjutan: OpenIntro Statistics , Penn State STAT 500 , dan dokumentasi scipy.stats .