1. Pengenalan Matplotlib
Matplotlib adalah library visualisasi data paling populer di Python. Matplotlib menyediakan cara yang fleksibel dan powerful untuk membuat grafik statis, animasi, dan interaktif. Hampir semua library visualisasi Python lainnya (Seaborn, Plotly, Pandas plotting) dibangun di atas Matplotlib.
Modul utama yang digunakan adalah matplotlib.pyplot — antarmuka mirip MATLAB untuk membuat grafik dengan cepat.
Jenis Grafik yang Tersedia
| Jenis Grafik | Fungsi | Cocok Untuk |
|---|---|---|
| Line Plot | plt.plot() | Tren data sepanjang waktu (time series) |
| Bar Chart | plt.bar() | Perbandingan antar kategori |
| Scatter Plot | plt.scatter() | Hubungan antara dua variabel |
| Histogram | plt.hist() | Distribusi frekuensi data |
| Pie Chart | plt.pie() | Proporsi bagian dari keseluruhan |
| Box Plot | plt.boxplot() | Sebaran data dan outlier |
| Heatmap | plt.imshow() | Matriks korelasi, intensitas |
┌──────────────────────────────────────────────────────┐ │ ARSITEKTUR MATPLOTLIB │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ Scripting Layer (pyplot) │ │ │ │ plt.plot(), plt.show(), plt.title() │ │ │ │ → Interface sederhana, cepat │ │ │ └──────────────────────┬───────────────────────┘ │ │ │ │ │ ┌──────────────────────▼───────────────────────┐ │ │ │ Artist Layer (Object-Oriented) │ │ │ │ Figure, Axes, Axis, Line2D, Text │ │ │ │ → Kontrol penuh atas setiap elemen │ │ │ └──────────────────────┬───────────────────────┘ │ │ │ │ │ ┌──────────────────────▼───────────────────────┐ │ │ │ Backend Layer (Rendering) │ │ │ │ Agg, PDF, SVG, GTK, Tkinter │ │ │ │ → Render ke layar atau file │ │ │ └──────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────┘
2. Instalasi dan Setup
# Instal Matplotlib pip install matplotlib # Verifikasi python -c "import matplotlib; print(matplotlib.__version__)" # Output: 3.9.0
Setup untuk Berbagai Environment
# Import konvensi
import matplotlib.pyplot as plt
import numpy as np
# Untuk Jupyter Notebook — tampilkan grafik inline
# %matplotlib inline
# Untuk Jupyter Notebook — grafik interaktif
# %matplotlib widget
# Set style global (opsional)
plt.style.use('seaborn-v0_8-darkgrid') # Style modern
# plt.style.use('ggplot') # Style R-like
# plt.style.use('dark_background') # Tema gelap
# Cek style yang tersedia
print(plt.style.available)
# Set DPI untuk tampilan yang lebih tajam
plt.rcParams['figure.dpi'] = 100
plt.rcParams['savefig.dpi'] = 150
# Set font
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.size'] = 12
3. Line Plot
Line plot adalah jenis grafik paling dasar — cocok untuk menampilkan tren data sepanjang waktu atau urutan.
Line Plot Dasar
import matplotlib.pyplot as plt
import numpy as np
# Data sederhana
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 4, 5, 7, 6, 8, 9, 10, 12, 11]
# Membuat line plot
plt.figure(figsize=(10, 6))
plt.plot(x, y, marker='o', color='blue', linewidth=2, markersize=8)
plt.title('Pertumbuhan Penjualan Bulanan', fontsize=16, fontweight='bold')
plt.xlabel('Bulan', fontsize=12)
plt.ylabel('Penjualan (Juta Rp)', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Multiple Lines
import matplotlib.pyplot as plt
import numpy as np
bulan = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun']
produk_a = [45, 52, 58, 63, 70, 78]
produk_b = [30, 35, 48, 55, 60, 65]
produk_c = [20, 28, 32, 40, 45, 52]
plt.figure(figsize=(12, 6))
# Plot tiga lini dengan gaya berbeda
plt.plot(bulan, produk_a, 'b-o', label='Laptop', linewidth=2, markersize=8)
plt.plot(bulan, produk_b, 'r--s', label='Mouse', linewidth=2, markersize=8)
plt.plot(bulan, produk_c, 'g-.^', label='Keyboard', linewidth=2, markersize=8)
plt.title('Tren Penjualan Produk (2024)', fontsize=16, fontweight='bold')
plt.xlabel('Bulan', fontsize=12)
plt.ylabel('Unit Terjual', fontsize=12)
plt.legend(fontsize=11, loc='upper left')
plt.grid(True, alpha=0.3)
plt.ylim(0, 90)
# Anotasi pada titik tertentu
plt.annotate('Target tercapai!', xy=(5, 78), xytext=(3, 82),
fontsize=10, color='blue',
arrowprops=dict(arrowstyle='->', color='blue'))
plt.tight_layout()
plt.show()
Format string singkat: 'b-o' = biru + garis + lingkaran. Warna: r(merah), g(hijau), b(biru), k(hitam). Garis: -(solid), --(putus), -.(titik-garis). Marker: o(lingkaran), s(kotak), ^(segitiga), D(diamond).
4. Bar Chart
Bar chart cocok untuk membandingkan nilai antar kategori. Matplotlib mendukung bar vertikal, horizontal, stacked, dan grouped.
import matplotlib.pyplot as plt
import numpy as np
# ===== Vertical Bar Chart =====
kota = ['Jakarta', 'Bandung', 'Surabaya', 'Medan', 'Makassar']
populasi = [10.56, 8.20, 5.85, 4.10, 3.25]
plt.figure(figsize=(10, 6))
bars = plt.bar(kota, populasi, color=['#3498db', '#2ecc71', '#e74c3c', '#f39c12', '#9b59b6'],
edgecolor='white', linewidth=1.5)
# Tambahkan label nilai di atas bar
for bar, val in zip(bars, populasi):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.15,
f'{val}M', ha='center', fontsize=11, fontweight='bold')
plt.title('Populasi Kota Terbesar Indonesia (Juta)', fontsize=16, fontweight='bold')
plt.xlabel('Kota', fontsize=12)
plt.ylabel('Populasi (Juta)', fontsize=12)
plt.ylim(0, 13)
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()
Grouped Bar Chart
import matplotlib.pyplot as plt
import numpy as np
# Data untuk grouped bar chart
departemen = ['IT', 'HR', 'Finance', 'Marketing']
gaji_2023 = [8500, 6200, 7800, 7000]
gaji_2024 = [9200, 6800, 8500, 7600]
x = np.arange(len(departemen))
width = 0.35
fig, ax = plt.subplots(figsize=(10, 6))
bars1 = ax.bar(x - width/2, gaji_2023, width, label='2023', color='#3498db')
bars2 = ax.bar(x + width/2, gaji_2024, width, label='2024', color='#e74c3c')
ax.set_title('Perbandingan Rata-rata Gaji per Departemen', fontsize=16, fontweight='bold')
ax.set_xlabel('Departemen', fontsize=12)
ax.set_ylabel('Gaji (Ribu Rp)', fontsize=12)
ax.set_xticks(x)
ax.set_xticklabels(departemen)
ax.legend(fontsize=11)
ax.grid(axis='y', alpha=0.3)
# Label pada bar
for bar in bars1:
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 50,
f'{bar.get_height():,}', ha='center', fontsize=9)
for bar in bars2:
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 50,
f'{bar.get_height():,}', ha='center', fontsize=9)
plt.tight_layout()
plt.show()
5. Scatter Plot
Scatter plot digunakan untuk menampilkan hubungan (korelasi) antara dua variabel numerik. Setiap titik mewakili satu observasi.
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
# Data: jam belajar vs nilai ujian
jam_belajar = np.random.uniform(1, 10, 50)
nilai_ujian = 40 + 5 * jam_belajar + np.random.normal(0, 5, 50)
warna = np.where(nilai_ujian >= 70, '#2ecc71', '#e74c3c')
plt.figure(figsize=(10, 7))
scatter = plt.scatter(jam_belajar, nilai_ujian, c=warna,
s=100, alpha=0.7, edgecolors='white', linewidth=1)
# Garis tren (linear regression)
z = np.polyfit(jam_belajar, nilai_ujian, 1)
p = np.poly1d(z)
x_line = np.linspace(1, 10, 100)
plt.plot(x_line, p(x_line), 'b--', linewidth=2, label=f'Tren: y={z[0]:.1f}x+{z[1]:.1f}')
plt.title('Hubungan Jam Belajar vs Nilai Ujian', fontsize=16, fontweight='bold')
plt.xlabel('Jam Belajar per Hari', fontsize=12)
plt.ylabel('Nilai Ujian', fontsize=12)
plt.legend(fontsize=11)
plt.grid(True, alpha=0.3)
# Tambah anotasi
plt.axhline(y=70, color='orange', linestyle=':', alpha=0.7, label='KKM = 70')
plt.legend(fontsize=11)
plt.tight_layout()
plt.show()
6. Histogram dan Pie Chart
Histogram
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
# Distribusi nilai ujian
nilai = np.random.normal(loc=75, scale=12, size=200)
nilai = np.clip(nilai, 0, 100) # Batasi 0-100
plt.figure(figsize=(10, 6))
n, bins, patches = plt.hist(nilai, bins=20, color='#3498db',
edgecolor='white', alpha=0.8)
# Warna bar berdasarkan rentang
for patch, left_edge in zip(patches, bins[:-1]):
if left_edge < 60:
patch.set_facecolor('#e74c3c') # Merah (gagal)
elif left_edge < 75:
patch.set_facecolor('#f39c12') # Kuning (cukup)
else:
patch.set_facecolor('#2ecc71') # Hijau (baik)
plt.axvline(x=75, color='black', linestyle='--', linewidth=2, label=f'Mean: {nilai.mean():.1f}')
plt.title('Distribusi Nilai Ujian (200 Mahasiswa)', fontsize=16, fontweight='bold')
plt.xlabel('Nilai', fontsize=12)
plt.ylabel('Frekuensi', fontsize=12)
plt.legend(fontsize=11)
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()
Pie Chart
import matplotlib.pyplot as plt
# Data market share
perusahaan = ['BeebaneLabs', 'Kompetitor A', 'Kompetitor B', 'Kompetitor C', 'Lainnya']
market_share = [35, 25, 20, 12, 8]
colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#95a5a6']
explode = (0.05, 0, 0, 0, 0) # Sorong slice pertama
plt.figure(figsize=(10, 8))
wedges, texts, autotexts = plt.pie(
market_share,
labels=perusahaan,
colors=colors,
explode=explode,
autopct='%1.1f%%', # Tampilkan persentase
startangle=140, # Rotasi awal
shadow=True,
textprops={'fontsize': 12}
)
# Style teks persentase
for autotext in autotexts:
autotext.set_fontweight('bold')
autotext.set_color('white')
plt.title('Market Share Cloud Indonesia 2024', fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
plt.show()
7. Subplots
Subplots memungkinkan Anda menampilkan beberapa grafik dalam satu figure — sangat berguna untuk membandingkan data atau membuat dashboard.
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
# ===== Subplot dengan plt.subplot() =====
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Dashboard Analisis Data Penjualan', fontsize=18, fontweight='bold', y=1.02)
# Plot 1: Line Plot (atas kiri)
bulan = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun']
penjualan = [45, 52, 58, 63, 70, 78]
axes[0, 0].plot(bulan, penjualan, 'b-o', linewidth=2, markersize=8)
axes[0, 0].set_title('Tren Penjualan Bulanan', fontsize=13, fontweight='bold')
axes[0, 0].set_ylabel('Unit Terjual')
axes[0, 0].grid(True, alpha=0.3)
# Plot 2: Bar Chart (atas kanan)
kota = ['Jakarta', 'Bandung', 'Surabaya', 'Medan']
pendapatan = [850, 620, 540, 380]
colors = ['#3498db', '#2ecc71', '#e74c3c', '#f39c12']
axes[0, 1].bar(kota, pendapatan, color=colors, edgecolor='white')
axes[0, 1].set_title('Pendapatan per Kota (Juta Rp)', fontsize=13, fontweight='bold')
axes[0, 1].set_ylabel('Pendapatan (Juta)')
axes[0, 1].grid(axis='y', alpha=0.3)
# Plot 3: Scatter Plot (bawah kiri)
jam = np.random.uniform(1, 10, 40)
nilai = 40 + 5 * jam + np.random.normal(0, 5, 40)
axes[1, 0].scatter(jam, nilai, c='#9b59b6', s=80, alpha=0.7, edgecolors='white')
axes[1, 0].set_title('Jam Belajar vs Nilai', fontsize=13, fontweight='bold')
axes[1, 0].set_xlabel('Jam Belajar')
axes[1, 0].set_ylabel('Nilai')
axes[1, 0].grid(True, alpha=0.3)
# Plot 4: Pie Chart (bawah kanan)
departemen = ['IT', 'HR', 'Finance', 'Marketing']
budget = [40, 20, 25, 15]
axes[1, 1].pie(budget, labels=departemen, autopct='%1.1f%%',
colors=['#3498db', '#2ecc71', '#e74c3c', '#f39c12'],
startangle=90)
axes[1, 1].set_title('Budget per Departemen', fontsize=13, fontweight='bold')
plt.tight_layout()
plt.show()
8. Styling dan Kustomisasi
Matplotlib Styles
import matplotlib.pyplot as plt
import numpy as np
# Cek semua style yang tersedia
styles = plt.style.available
print(styles[:10])
# ['Solarize_Light2', '_classic_test_patch', 'bmh', 'dark_background',
# 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn-v0_8', ...]
# Menggunakan style
plt.style.use('seaborn-v0_8-whitegrid') # Modern & clean
# plt.style.use('ggplot') # Seperti R
# plt.style.use('fivethirtyeight') # Seperti website FiveThirtyEight
# plt.style.use('dark_background') # Tema gelap
# Context manager untuk style sementara
with plt.style.context('dark_background'):
plt.figure(figsize=(8, 5))
plt.plot([1, 2, 3, 4], [1, 4, 2, 3], 'o-', linewidth=3, markersize=10)
plt.title('Grafik dengan Dark Theme')
plt.show()
Kustomisasi Detail
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(12, 7))
# Data
np.random.seed(42)
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# Plot dengan kustomisasi lengkap
ax.plot(x, y1, color='#3498db', linewidth=2.5, label='sin(x)',
linestyle='-', marker='', zorder=2)
ax.plot(x, y2, color='#e74c3c', linewidth=2.5, label='cos(x)',
linestyle='--', marker='', zorder=2)
# Fill area antara kurva
ax.fill_between(x, y1, y2, alpha=0.15, color='#9b59b6', label='Selisih')
# Kustomisasi axes
ax.set_title('Fungsi Sinus dan Kosinus', fontsize=18, fontweight='bold', pad=15)
ax.set_xlabel('Sumbu X (radian)', fontsize=14, labelpad=10)
ax.set_ylabel('Sumbu Y', fontsize=14, labelpad=10)
# Legend
ax.legend(fontsize=12, loc='upper right', frameon=True,
fancybox=True, shadow=True, framealpha=0.9)
# Grid
ax.grid(True, linestyle=':', alpha=0.5)
# Spine (border) kustomisasi
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_linewidth(0.5)
ax.spines['bottom'].set_linewidth(0.5)
# Tick
ax.tick_params(axis='both', which='major', labelsize=11, width=0.5)
ax.set_xlim(0, 10)
ax.set_ylim(-1.5, 1.5)
# Text anotasi
ax.annotate('Maksimum', xy=(np.pi/2, 1), xytext=(4, 1.3),
fontsize=11, fontweight='bold', color='#3498db',
arrowprops=dict(arrowstyle='->', color='#3498db', lw=1.5))
plt.tight_layout()
plt.show()
9. Integrasi dengan Pandas
Pandas memiliki integrasi built-in dengan Matplotlib — Anda bisa membuat grafik langsung dari DataFrame dengan satu baris kode.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Buat DataFrame
np.random.seed(42)
df = pd.DataFrame({
'Bulan': ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun'],
'Laptop': [45, 52, 58, 63, 70, 78],
'Mouse': [200, 180, 220, 250, 230, 260],
'Keyboard': [80, 95, 88, 110, 105, 120]
})
# Quick plot langsung dari DataFrame
df.set_index('Bulan').plot(kind='line', figsize=(10, 6), marker='o', linewidth=2)
plt.title('Penjualan Produk per Bulan', fontsize=16, fontweight='bold')
plt.ylabel('Unit Terjual')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Bar chart dari DataFrame
df.set_index('Bulan').plot(kind='bar', figsize=(10, 6), width=0.8)
plt.title('Penjualan per Bulan (Bar Chart)', fontsize=16, fontweight='bold')
plt.ylabel('Unit Terjual')
plt.xticks(rotation=0)
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()
# Histogram dari kolom DataFrame
data_nilai = pd.DataFrame({
'Matematika': np.random.normal(75, 10, 100),
'Fisika': np.random.normal(68, 15, 100),
'Kimia': np.random.normal(72, 12, 100)
})
data_nilai.plot(kind='hist', alpha=0.5, bins=20, figsize=(10, 6))
plt.title('Distribusi Nilai Ujian', fontsize=16, fontweight='bold')
plt.xlabel('Nilai')
plt.ylabel('Frekuensi')
plt.tight_layout()
plt.show()
# Scatter dari DataFrame
df_sales = pd.DataFrame({
'Budget_Iklan': np.random.uniform(10, 100, 30),
'Penjualan': None
})
df_sales['Penjualan'] = df_sales['Budget_Iklan'] * 5 + np.random.normal(0, 20, 30)
df_sales.plot.scatter(x='Budget_Iklan', y='Penjualan', figsize=(10, 6),
c='Penjualan', cmap='viridis', s=100)
plt.title('Budget Iklan vs Penjualan', fontsize=16, fontweight='bold')
plt.tight_layout()
plt.show()
10. Menyimpan Grafik
import matplotlib.pyplot as plt
import numpy as np
# Buat grafik
plt.figure(figsize=(10, 6))
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), label='sin(x)', linewidth=2)
plt.plot(x, np.cos(x), label='cos(x)', linewidth=2)
plt.title('Fungsi Trigonometri')
plt.legend()
plt.grid(True, alpha=0.3)
# Simpan dalam berbagai format
plt.savefig('grafik.png', dpi=150, bbox_inches='tight', facecolor='white')
plt.savefig('grafik.pdf', bbox_inches='tight')
plt.savefig('grafik.svg', bbox_inches='tight')
plt.savefig('grafik.jpg', dpi=200, bbox_inches='tight', quality=95)
# Penjelasan parameter:
# dpi = resolusi (150 untuk web, 300 untuk cetak)
# bbox_inches = 'tight' menghilangkan whitespace berlebih
# facecolor = warna background
# format = ditentukan dari ekstensi nama file
plt.show()
# Format yang didukung:
# PNG → Web, presentasi (lossless)
# PDF → Dokumen, cetak (vector)
# SVG → Web, editing (vector)
# JPG → Web (lossy, ukuran kecil)
# EPS → Jurnal ilmiah (vector)
11. Tips Visualisasi yang Baik
1. Selalu beri judul dan label sumbu. Grafik tanpa konteks tidak informatif.
2. Gunakan warna yang bermakna. Merah untuk negatif, hijau untuk positif.
3. Hindari terlalu banyak elemen. Less is more — jangan terlalu ramai.
4. Pilih jenis grafik yang tepat. Line untuk tren, bar untuk perbandingan, scatter untuk korelasi.
5. Perhatikan ukuran dan DPI. Sesuaikan untuk target (web/cetak).
6. Gunakan legend yang jelas. Terutama jika ada beberapa seri data.
import matplotlib.pyplot as plt
import numpy as np
# Template grafik profesional
def buat_grafik_profesional():
"""Template grafik dengan standar profesional."""
# Setup
fig, ax = plt.subplots(figsize=(12, 7))
# Data
np.random.seed(42)
kategori = ['Q1', 'Q2', 'Q3', 'Q4']
revenue = [2.5, 3.2, 3.8, 4.5]
target = [3.0, 3.5, 4.0, 4.2]
x = np.arange(len(kategori))
width = 0.35
# Plot
bars = ax.bar(x - width/2, revenue, width, label='Revenue Aktual',
color='#3498db', edgecolor='white', zorder=3)
ax.plot(x, target, 'ro-', linewidth=2.5, markersize=10,
label='Target', zorder=4)
# Kustomisasi
ax.set_title('Revenue vs Target per Quarter 2024',
fontsize=18, fontweight='bold', pad=20)
ax.set_xlabel('Quarter', fontsize=14, labelpad=10)
ax.set_ylabel('Revenue (Miliar Rp)', fontsize=14, labelpad=10)
ax.set_xticks(x)
ax.set_xticklabels(kategori, fontsize=12)
ax.legend(fontsize=12, loc='upper left', frameon=True,
fancybox=True, shadow=True)
ax.grid(axis='y', linestyle=':', alpha=0.5, zorder=0)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# Label pada bar
for bar in bars:
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.05,
f'Rp {bar.get_height():.1f}T', ha='center',
fontsize=11, fontweight='bold')
plt.tight_layout()
plt.savefig('grafik_profesional.png', dpi=150, bbox_inches='tight')
plt.show()
buat_grafik_profesional()
12. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Matplotlib: