Chapter Diagram Batang di Section Visualisasi Data menutup pembahasannya dengan satu janji: grafik yang sama akan kita gambar sendiri dengan matplotlib pada section ini. Janji itu kita bayar sekarang. Seluruh data contoh — nilai 30 siswa, penjualan kopi, harga beras 12 bulan, jam belajar terhadap nilai, dan dua kelas yang dibandingkan — dipakai ulang apa adanya, sehingga fokus kita bergeser dari membaca grafik ke memproduksinya. Chapter ini memperkenalkan dua gaya penulisan kode matplotlib, menjelaskan cara kerjanya di server tanpa layar, lalu menggambar kelima grafik satu per satu.
Dua Gaya Menulis Kode: pyplot dan Object-Oriented #
Kode matplotlib di internet datang dalam dua gaya, dan mengenali keduanya mencegah kebingungan saat membaca contoh orang lain. Gaya pertama memakai antarmuka pyplot yang kita impor sebagai plt: fungsi seperti plt.hist atau plt.title bekerja pada figur yang sedang aktif — matplotlib mengingat figur itu di balik layar, dan kita tidak pernah memegang objeknya secara eksplisit. Gaya kedua bersifat object-oriented: kita membuat fig, ax = plt.subplots() secara eksplisit, lalu memanggil metode ax.hist dan ax.set_title pada objek ax itu.
| Aspek | Gaya plt | Gaya ax (object-oriented) |
|---|---|---|
| Panjang kode | pendek, cocok satu grafik | sedikit lebih panjang |
| Figur banyak panel | tidak praktis | plt.subplots(1, 2) langsung memberi dua ax |
| Referensi resmi | banyak contoh singkat | gaya yang dipakai dokumentasi matplotlib |
| Cocok untuk | eksplorasi cepat, chapter ini | laporan, fungsi gambar yang dipakai ulang |
Kebijakan kita pada chapter ini: gaya plt untuk contoh-contoh cepat, gaya ax ditunjukkan sebagai padanannya sekali di bagian histogram. Keduanya menghasilkan gambar yang identik — pilihan gaya menyangkut struktur kode, bukan hasil akhirnya.
Backend Tanpa Layar: Menyimpan, Bukan Menampilkan #
Tutorial matplotlib sering menutup contoh dengan plt.show(), yang membuka jendela grafik interaktif di layar. Analisis nyata kerap berjalan di server tanpa layar — dan di lingkungan seperti itu plt.show() tidak punya jendela untuk dibuka. matplotlib mengatasinya dengan konsep backend: modul perender yang bisa dipilih. Backend Agg merender gambar langsung ke berkas tanpa memerlukan display, dan pada server tanpa layar matplotlib memilih Agg secara otomatis. Bila kita ingin memastikannya, panggil matplotlib.use("Agg") sebelum mengimpor pyplot — contoh pertama di bawah memakai pola eksplisit ini, contoh-contoh berikutnya mengandalkan pemilihan otomatis.
Konsekuensi kerjanya: hasil setiap grafik disimpan dengan plt.savefig("nama.png"), lalu figur ditutup dengan plt.close(). Pemanggilan close() terlihat remeh, tetapi pada skrip yang menggambar puluhan grafik dalam loop, figur yang tidak ditutup menumpuk di memori dan memperlambat eksekusi — kebiasaan menutup figur sejak awal murah dan menghemat banyak waktu.
Histogram dari Data 30 Siswa #
Grafik pertama menggambar ulang histogram nilai 30 siswa dari chapter Histogram. Parameter bins=5 membagi rentang data menjadi lima kelas, dan edgecolor="black" memberi garis tepi pada tiap batang sehingga batang yang bersebelahan tetap terbedakan. Nilai kembalian plt.hist menarik untuk dicetak: pasangan frekuensi dan batas kelas — angka yang sama dengan tabel frekuensi yang dulu dihitung manual.
import matplotlib
matplotlib.use("Agg") # pilih backend tanpa layar SEBELUM mengimpor pyplot
import matplotlib.pyplot as plt
nilai = [60, 62, 63, 65, 65, 67, 68, 68, 69, 70,
70, 71, 72, 72, 73, 74, 74, 74, 75, 75,
76, 77, 77, 78, 79, 80, 81, 82, 83, 84]
plt.figure()
frekuensi, batas, _ = plt.hist(nilai, bins=5, edgecolor="black")
plt.xlabel("Nilai ulangan")
plt.ylabel("Jumlah siswa")
plt.title("Sebaran Nilai 30 Siswa")
plt.savefig("histogram_nilai.png")
plt.close()
print("frekuensi kelas :", [int(f) for f in frekuensi])
print("batas kelas :", [f"{b:.1f}" for b in batas])
print("jumlah batas :", len(batas))Output yang Dihasilkan:
frekuensi kelas : [3, 6, 9, 7, 5]
batas kelas : ['60.0', '64.8', '69.6', '74.4', '79.2', '84.0']
jumlah batas : 6Mari kita bedah kode di atas:
- Baris 1-3 (backend):
matplotlib.use("Agg")dipanggil sebelumimport pyplotkarena backend harus terpasang saat pyplot diimpor; setelah itu semua perenderan menuju berkas. - Baris 10 (
plt.hist): mengembalikan tiga objek — frekuensi tiap kelas, batas kelas (enam batas untuk lima kelas), dan kumpulan batang; dua yang pertama kita simpan untuk diverifikasi. - Baris 11-13 (label):
xlabel,ylabel, dantitlebukan hiasan — tanpa “Jumlah siswa” pembaca tidak tahu sumbu vertikal menghitung orang, dan tanpa “Nilai ulangan” skala 60-84 bisa disangka persentase. - Baris 14-15 (simpan dan tutup): gambar tersimpan sebagai
histogram_nilai.png, figur ditutup agar memori bersih.
Gambar yang tersimpan memperlihatkan lima batang menempel tanpa celah — persis karakter histogram data numerik yang dibahas chapter Histogram. Puncaknya di kelas tengah dengan 9 siswa, turun ke 6 lalu 3 di sisi kiri dan ke 7 lalu 5 di sisi kanan: sebaran menumpuk di tengah. Frekuensi [3, 6, 9, 7, 5] identik dengan tabel frekuensi manual kelas 60-64 sampai 80-84 — kebetulan yang menjelaskan dirinya sendiri: karena seluruh data berupa bilangan bulat, batas pecahan 64.8 memisahkan nilai 64 dari 65 dengan cara yang sama seperti batas kelas manual.
Padanan Object-Oriented #
Histogram yang sama dalam gaya ax tampak seperti ini:
import matplotlib.pyplot as plt
nilai = [60, 62, 63, 65, 65, 67, 68, 68, 69, 70,
70, 71, 72, 72, 73, 74, 74, 74, 75, 75,
76, 77, 77, 78, 79, 80, 81, 82, 83, 84]
fig, ax = plt.subplots()
ax.hist(nilai, bins=5, edgecolor="black")
ax.set_xlabel("Nilai ulangan")
ax.set_ylabel("Jumlah siswa")
ax.set_title("Sebaran Nilai 30 Siswa")
fig.savefig("histogram_oo.png")Tiap fungsi plt punya padanan metode ax: plt.hist menjadi ax.hist, plt.xlabel menjadi ax.set_xlabel. Gambar yang dihasilkan identik dengan versi sebelumnya. Kekuatan gaya ini baru terasa ketika satu figur menampung beberapa panel — fig, ax = plt.subplots(1, 2) mengembalikan dua objek ax yang masing-masing bisa diisi grafik berbeda, misalnya histogram dua kelas berdampingan.
Diagram Batang, Line Chart, Scatter, dan Box Plot #
Empat grafik sisanya dari Section Visualisasi Data kita gambar dalam satu blok — tiap grafik menempati figur sendiri, dan dua angka ringkasan dicetak sebagai pemeriksaan silang.
import matplotlib.pyplot as plt
kopi = ["Kopi susu", "Americano", "Latte", "Matcha", "Espresso"]
cangkir = [120, 85, 60, 45, 30]
beras = [12500, 12800, 12700, 13100, 13400, 13300,
13600, 13900, 13800, 14200, 14500, 14400]
jam = [2, 3, 4, 5, 6, 7]
nilai = [65, 70, 75, 82, 86, 91]
kelas_a = [68, 75, 75, 81, 84, 88, 90, 92, 97]
kelas_b = [74, 78, 80, 81, 82, 83, 85, 87, 90]
plt.figure()
plt.bar(kopi, cangkir, edgecolor="black")
plt.ylabel("Cangkir per hari")
plt.title("Penjualan Kopi Kafe")
plt.savefig("bar_kopi.png")
plt.close()
plt.figure()
plt.plot(range(1, 13), beras, marker="o")
plt.xlabel("Bulan ke-")
plt.ylabel("Harga beras (Rp/kg)")
plt.title("Harga Beras 12 Bulan")
plt.grid(True)
plt.savefig("line_beras.png")
plt.close()
plt.figure()
plt.scatter(jam, nilai)
plt.xlabel("Jam belajar per hari")
plt.ylabel("Nilai ulangan")
plt.title("Jam Belajar terhadap Nilai")
plt.savefig("scatter_belajar.png")
plt.close()
plt.figure()
plt.boxplot([kelas_a, kelas_b], tick_labels=["Kelas A", "Kelas B"])
plt.ylabel("Nilai")
plt.title("Perbandingan Sebaran Dua Kelas")
plt.savefig("boxplot_kelas.png")
plt.close()
print("total cangkir :", sum(cangkir))
print("mean harga beras:", f"{sum(beras) / len(beras):.2f} Rp/kg")Output yang Dihasilkan:
total cangkir : 340
mean harga beras: 13516.67 Rp/kgEmpat gambar yang tersimpan memuat pesan yang persis sama dengan sketsa teks pada section teori:
| Grafik | Fungsi | Bentuk yang terlihat |
|---|---|---|
bar_kopi.png | plt.bar(kategori, nilai) | kopi susu menjulang 120 cangkir — 35.29 persen dari total 340 — sementara espresso terpendek 30 |
line_beras.png | plt.plot(x, y, marker="o") | garis naik dari 12500 menuju puncak 14500 pada bulan ke-11, turun tipis ke 14400, dengan empat lekukan kecil di bulan 3, 6, 9, dan 12 |
scatter_belajar.png | plt.scatter(x, y) | enam titik berbaris dari kiri bawah ke kanan atas — sebaran rapat dengan korelasi 0.998 |
boxplot_kelas.png | plt.boxplot([a, b]) | kotak Kelas A lebar (IQR 15) dengan whisker panjang, kotak Kelas B sempit (IQR 5); median 84 berbanding 82 |
Beberapa detail kode layak dicatat. Argumen marker="o" pada line chart menandai tiap titik bulan agar nilai data terlihat, bukan hanya garis penghubungnya; plt.grid(True) membantu mata membaca level harga antar penanda sumbu. Parameter tick_labels pada boxplot memberi nama kedua kelompok di sumbu-x — tanpa label, pembaca hanya melihat dua kotak anonim. Pola plt.figure() di awal tiap grafik memastikan grafik baru tidak menumpuk di atas figur sebelumnya yang sudah ditutup.
Skrip Terpadu: visualisasi_lengkap.py #
Dua grafik pertama kita rangkai menjadi skrip utuh yang dapat diunduh dan dijalankan ulang — pola yang sama dengan skrip pendukung chapter-chapter sebelumnya di section ini.
"""visualisasi_lengkap.py — dua grafik dasar dari data Section Visualisasi Data."""
import matplotlib
matplotlib.use("Agg") # backend tanpa layar: gambar disimpan, bukan ditampilkan
import matplotlib.pyplot as plt
nilai = [60, 62, 63, 65, 65, 67, 68, 68, 69, 70,
70, 71, 72, 72, 73, 74, 74, 74, 75, 75,
76, 77, 77, 78, 79, 80, 81, 82, 83, 84]
kopi = ["Kopi susu", "Americano", "Latte", "Matcha", "Espresso"]
cangkir = [120, 85, 60, 45, 30]
plt.figure() # grafik 1: histogram sebaran nilai 30 siswa
plt.hist(nilai, bins=5, edgecolor="black")
plt.xlabel("Nilai ulangan")
plt.ylabel("Jumlah siswa")
plt.title("Sebaran Nilai 30 Siswa")
plt.savefig("histogram_nilai.png")
plt.close()
print("histogram_nilai.png tersimpan")
plt.figure() # grafik 2: diagram batang penjualan kopi
plt.bar(kopi, cangkir, edgecolor="black")
plt.ylabel("Cangkir per hari")
plt.title("Penjualan Kopi Kafe")
plt.savefig("bar_kopi.png")
plt.close()
print("bar_kopi.png tersimpan")
print(f"total cangkir : {sum(cangkir)}")
print(f"menu paling laku: {kopi[cangkir.index(max(cangkir))]} ({max(cangkir)} cangkir)")Output yang Dihasilkan:
histogram_nilai.png tersimpan
bar_kopi.png tersimpan
total cangkir : 340
menu paling laku: Kopi susu (120 cangkir)Skrip ini sengaja mencetak konfirmasi tiap berkas yang tersimpan. Pada server tanpa layar kita tidak bisa langsung melihat gambar, dan baris keluaran seperti histogram_nilai.png tersimpan menjadi bukti tercepat bahwa perenderan berhasil — nama menu paling laku bahkan dihitung dari data lewat cangkir.index(max(cangkir)), bukan diketik manual. Baris terakhir skrip memakai f-string untuk merangkai angka dan teks, pola format yang sama dengan seluruh contoh section ini. Galeri lengkap jenis grafik beserta parameternya terdokumentasi di matplotlib.org
, dan panduan memilih bentuk grafik yang tepat dirangkum dalam NIST/SEMATECH e-Handbook
.
Grafik memperlihatkan wajah data, tetapi keputusan statistik membutuhkan lebih dari gambar: peluang, kuantil, dan ekor distribusi. Chapter berikutnya memperkenalkan objek-objek distribusi scipy.stats yang menghitung semua besaran itu dalam satu panggilan fungsi — dan tabel-tabel yang dulu kita susun dengan tangan akan terverifikasi ulang angka demi angka.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
visualisasi_lengkap.py
Unduh berkas"""visualisasi_lengkap.py — dua grafik dasar dari data Section Visualisasi Data."""
import matplotlib
matplotlib.use("Agg") # backend tanpa layar: gambar disimpan, bukan ditampilkan
import matplotlib.pyplot as plt
nilai = [60, 62, 63, 65, 65, 67, 68, 68, 69, 70,
70, 71, 72, 72, 73, 74, 74, 74, 75, 75,
76, 77, 77, 78, 79, 80, 81, 82, 83, 84]
kopi = ["Kopi susu", "Americano", "Latte", "Matcha", "Espresso"]
cangkir = [120, 85, 60, 45, 30]
plt.figure() # grafik 1: histogram sebaran nilai 30 siswa
plt.hist(nilai, bins=5, edgecolor="black")
plt.xlabel("Nilai ulangan")
plt.ylabel("Jumlah siswa")
plt.title("Sebaran Nilai 30 Siswa")
plt.savefig("histogram_nilai.png")
plt.close()
print("histogram_nilai.png tersimpan")
plt.figure() # grafik 2: diagram batang penjualan kopi
plt.bar(kopi, cangkir, edgecolor="black")
plt.ylabel("Cangkir per hari")
plt.title("Penjualan Kopi Kafe")
plt.savefig("bar_kopi.png")
plt.close()
print("bar_kopi.png tersimpan")
print(f"total cangkir : {sum(cangkir)}")
print(f"menu paling laku: {kopi[cangkir.index(max(cangkir))]} ({max(cangkir)} cangkir)")