Pada chapter sebelumnya kita mengarahkan pandangan ke banyak variabel sekaligus. Sekarang kita kembali ke tugas paling mendasar dalam eksplorasi data: memeriksa sebaran satu variabel numerik — nilai transaksi, durasi kunjungan, umur pelanggan. Dua grafik menjadi standar praktiknya: histogram yang memperlihatkan bentuk sebaran, dan boxplot yang meringkasnya menjadi lima angka kunci plus daftar pencilan. Pada chapter ini kita bedah keduanya sampai ke mekanismenya: bagaimana jumlah bin mengubah cerita histogram, bagaimana kotak dan kawatis boxplot dihitung dari kuartil, dan bagaimana keduanya bekerja saling melengkapi dalam satu figura.
Dua Alat untuk Satu Pertanyaan #
Keduanya menjawab pertanyaan yang sama — “bagaimana sebaran variabel ini?” — dengan cara yang berbeda. Histogram menampilkan bentuk lengkap sebaran batang demi batang, sedangkan boxplot meringkas sebaran menjadi ringkasan lima angka (five-number summary): minimum, kuartil pertama, median, kuartil ketiga, dan maksimum. Kekuatan dan keterbatasannya saling mengisi:
| Aspek | Histogram | Boxplot |
|---|---|---|
| Yang ditampilkan | bentuk sebaran lengkap | ringkasan lima angka + pencilan |
| Kekuatan | memperlihatkan dua puncak, kemencengan, celah | perbandingan antar kelompok dalam satu bidang |
| Keterbatasan | bergantung jumlah bin | bentuk di dalam kotak tidak terlihat |
| Penempatan terbaik | memeriksa satu variabel secara saksama | membandingkan beberapa kelompok |
Data latihan kita adalah nilai 60 transaksi Toko Kopi Kita dalam ribu rupiah, dibangkitkan dengan seed 42 ditambah satu pesanan besar senilai 120 ribu untuk rapat kantor — satu baris yang sengaja berbeda populasinya dari sisanya.
Histogram: Bin yang Mengubah Cerita #
Mekanisme bin sudah kita bedah pada chapter Grafik Distribusi, jadi di sini kita langsung mengamati konsekuensinya pada pembacaan. Dua jumlah bin yang berbeda menghasilkan dua cerita yang tidak persis sama:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
nilai = rng.normal(38, 9, 59).round().astype(int) # ribu rupiah
nilai = np.append(nilai, 120) # satu pesanan besar untuk rapat kantor
fig, (kiri, kanan) = plt.subplots(1, 2, figsize=(9, 3.5), sharey=True)
kiri.hist(nilai, bins=5, color="tab:blue", edgecolor="white")
kiri.set_title("Lima bin: bentuk umum")
kiri.set_xlabel("Nilai transaksi (ribu rupiah)")
kiri.set_ylabel("Jumlah transaksi")
kanan.hist(nilai, bins=20, color="tab:blue", edgecolor="white")
kanan.set_title("Dua puluh bin: detail lebih halus")
kanan.set_xlabel("Nilai transaksi (ribu rupiah)")
plt.show()Panel kiri memuat lima batang lebar: dua batang tinggi pada rentang 20-40 (31 transaksi) dan 40-60 (28 transaksi), tiga batang kosong, lalu satu batang kurus di ujung kanan rentang 100-120. Panel kanan memuat dua puluh batang kurus yang memperlihatkan puncak pada rentang 40-45 (16 transaksi), pinggiran yang menurun mulai dari rentang 25-30, dan satu batang sendirian di 115-120. Keduanya jujur, tetapi menonjolkan hal yang berbeda: panel kiri cukup untuk “mayoritas transaksi di bawah 60”, sedangkan panel kanan memperlihatkan bahwa sebaran utama berpusat di kisaran 30-50 — dan bahwa jarak si pesanan besar ke kelompok utamanya jauh lebih panjang daripada yang terkesan pada panel kiri.
Membedah Kotak: Kuartil, IQR, dan Pencilan #
Boxplot membangun seluruh tubuhnya dari kuartil. Kuartil membagi data terurut menjadi empat bagian sama banyak: Q1 menandai perempat bawah, median menandai tengah, Q3 menandai perempat atas. Kotak boxplot membentang dari Q1 sampai Q3 — lebarnya adalah IQR (interquartile range), ukuran sebaran yang kebal pencilan. Kawatis (whisker) menjulur dari kedua ujung kotak sampai ke nilai terjauh yang masih berada di dalam batas Q1 - 1,5 × IQR dan Q3 + 1,5 × IQR; nilai yang berada di luarnya digambar sebagai titik pencilan. Kita hitung semuanya secara terbuka:
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
nilai = rng.normal(38, 9, 59).round().astype(int) # ribu rupiah
nilai = np.append(nilai, 120) # satu pesanan besar untuk rapat kantor
transaksi = pd.Series(nilai, name="nilai")
q1 = transaksi.quantile(0.25)
q3 = transaksi.quantile(0.75)
iqr = q3 - q1
batas_bawah = q1 - 1.5 * iqr
batas_atas = q3 + 1.5 * iqr
pencilan = transaksi[(transaksi < batas_bawah) | (transaksi > batas_atas)]
print("Jumlah transaksi :", len(transaksi))
print("Rata-rata :", round(transaksi.mean(), 1))
print("Terkecil :", transaksi.min())
print("Terbesar :", transaksi.max())
print()
print("Kuartil 1 (Q1) :", q1)
print("Median :", transaksi.median())
print("Kuartil 3 (Q3) :", q3)
print("IQR (Q3 - Q1) :", iqr)
print("Batas bawah :", batas_bawah, "= Q1 - 1.5 x IQR")
print("Batas atas :", batas_atas, "= Q3 + 1.5 x IQR")
print("Pencilan :", pencilan.tolist())Output yang Dihasilkan:
Jumlah transaksi : 60
Rata-rata : 39.8
Terkecil : 20
Terbesar : 120
Kuartil 1 (Q1) : 33.75
Median : 39.0
Kuartil 3 (Q3) : 44.0
IQR (Q3 - Q1) : 10.25
Batas bawah : 18.375 = Q1 - 1.5 x IQR
Batas atas : 59.375 = Q3 + 1.5 x IQR
Pencilan : [120]Mari kita telaah baris-barisnya:
- Baris 4-6: 59 nilai transaksi reguler dibangkitkan dari sebaran normal dengan rata-rata 38 dan simpangan 9, lalu satu nilai 120 disisipkan — seed 42 menjamin angka-angka ini dapat direproduksi persis.
- Baris 10-11 (
quantile(0.25)danquantile(0.75)): pandas menghitung kuartil dari data terurut; hasilnya Q1 = 33,75 dan Q3 = 44, artinya 50% transaksi bernilai di antara kedua angka itu. - Baris 12-14: batas kawatis dihitung dengan rumus baku 1,5 × IQR; dengan IQR 10,25, semua nilai di luar rentang 18,375-59,375 berhak menjadi titik pencilan.
- Baris 15 (
pencilan): penyaringan boolean mengumpulkan nilai di luar batas — hanya si pesanan rapat kantor senilai 120.
Susunan angka-angka itu kemudian tergambar sebagai satu bentuk:
pencilan o 120 (di luar batas atas 59,375)
kawatis kanan | 57 (nilai terbesar di dalam batas)
kuartil 3 (Q3) | 44,0 ┐
median | 39,0 │ kotak = IQR 10,25
kuartil 1 (Q1) | 33,75 ┘
kawatis kiri | 20 (nilai terkecil di dalam batas)Kini kita gambar bentuknya, lengkap dengan anotasi bagiannya:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
nilai = rng.normal(38, 9, 59).round().astype(int)
nilai = np.append(nilai, 120)
fig, ax = plt.subplots(figsize=(6, 4.5))
ax.boxplot(nilai, vert=False, widths=0.35,
flierprops=dict(marker="o", markerfacecolor="tab:red",
markersize=7))
ax.annotate("kotak: Q1 sampai Q3", xy=(38.8, 1.18), fontsize=9)
ax.annotate("garis median", xy=(39, 0.83), xytext=(52, 0.7), fontsize=9,
arrowprops=dict(arrowstyle="->"))
ax.annotate("kawatis", xy=(48, 1.0), xytext=(62, 1.25), fontsize=9,
arrowprops=dict(arrowstyle="->"))
ax.annotate("pencilan", xy=(120, 1.0), xytext=(105, 1.32), fontsize=9,
arrowprops=dict(arrowstyle="->"))
ax.set_title("Anatomi Boxplot Nilai Transaksi")
ax.set_xlabel("Nilai transaksi (ribu rupiah)")
plt.show()Gambar yang muncul memuat satu kotak mendatar yang membentang dari 33,75 sampai 44 dengan garis median di tengahnya sedikit di kanan pusat kotak (39). Dua garis kawatis menjulur dari ujung kotak — kiri sampai 20 dan kanan sampai 57 — lalu satu titik merah berdiri sendiri di 120, jauh di sebelah kanan, sebagai satu-satunya pencilan. Setengah dari seluruh transaksi berada di dalam lebar kotak yang hanya sepanjang 10,25 ribu rupiah; itulah pesan yang disampaikan boxplot dalam sekali baca.
Dua baris kuncinya: vert=False meletakkan boxplot secara mendatar sehingga sumbu nilainya sejajar dengan sumbu histogram (keduanya membaca nilai dari kiri ke kanan), dan flierprops=dict(...) mengatur tampilan titik pencilan agar berupa lingkaran merah yang mudah diketahui.
Dua Sudut Pandang dalam Satu Figura #
Pada praktiknya kita hampir selalu menggambar keduanya bersamaan: histogram memperlihatkan bentuk sebaran yang disembunyikan boxplot, dan boxplot memperlihatkan ringkasan serta pencilan yang tersesat di antara batang histogram. Pola subplots 2×1 dengan sumbu bersama menjadikan keduanya sebidang:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
nilai = rng.normal(38, 9, 59).round().astype(int)
nilai = np.append(nilai, 120)
fig, (atas, bawah) = plt.subplots(2, 1, figsize=(6.5, 4.5),
sharex=True, height_ratios=[2, 1])
atas.hist(nilai, bins=12, color="tab:blue", edgecolor="white")
atas.set_title("Sebaran Nilai 60 Transaksi")
atas.set_ylabel("Jumlah transaksi")
bawah.boxplot(nilai, vert=False, widths=0.4)
bawah.set_xlabel("Nilai transaksi (ribu rupiah)")
bawah.set_yticks([])
plt.show()Gambar yang dihasilkan memuat dua lapis yang membaca sumbu yang sama: histogram dua belas batang di atas dengan puncak pada rentang 36,7-45 (24 transaksi), dan boxplot mendatar di bawahnya. Kotak boxplot tepat berada di bawah wilayah batang tertinggi, kawatis kanan berakhir di 57 dekat batang terakhir sebelum celah kosong, dan titik pencilan 120 sejajar persis dengan batang kurus di ujung kanan histogram. Perataan ini membuat kedua sudut pandang dapat diperiksa silang: nilai yang tampak sebagai ekor di histogram tampak sebagai kawatis di boxplot.
Dua argumen yang membuat komposisi ini rapi: sharex=True memaksa kedua bidang memakai rentang sumbu mendatar yang sama, dan height_ratios=[2, 1] memberi ruang dua bagian untuk histogram dan satu bagian untuk boxplot — proporsi yang lazim karena boxplot hanyalah ringkasan satu baris.
Rangkuman #
- Histogram dan boxplot menjawab pertanyaan yang sama dengan cara berbeda: bentuk lengkap lawan ringkasan lima angka; keduanya paling kuat saat digambar bersama.
- Jumlah bin mengubah cerita histogram: lima bin cukup untuk gambaran umum, dua puluh bin memperlihatkan pusat sebaran dan jarak pencilan yang lebih jujur.
- Kotak boxplot membentang dari Q1 sampai Q3 dengan lebar IQR; kawatis berhenti di nilai terjauh di dalam batas 1,5 × IQR, dan nilai di luarnya digambar sebagai titik pencilan.
- Kombinasi
subplots(2, 1, sharex=True, height_ratios=[2, 1])menyandingkan histogram dan boxplot pada sumbu yang sama sehingga keduanya dapat diperiksa silang. - Pencilan perlu diperiksa asal-usulnya: salah ketik dibuang, nilai dari populasi berbeda dianalisis terpisah.
Sebaran satu variabel kini terbaca dari dua sudut sekaligus. Pertanyaan berikutnya yang jamak muncul: apakah dua variabel numerik bergerak bersama? Titik-titik pada scatter plot menjawabnya — dan seiring membesarnya data, titik-titik itu menimbulkan persoalan tersendiri. Kita bedah tuntas pada chapter Scatter Plot.
Referensi #
- Matplotlib — Plot Types — referensi resmi histogram dan boxplot beserta statistiknya.
- Matplotlib — pyplot API Summary
— ringkasan fungsi
hist,boxplot, dansubplots. - Seaborn — Tutorial — panduan resmi seaborn, termasuk boxplot antar kelompok yang kita pakai pada chapter Visualisasi dengan Seaborn.