Membangun Dashboard Data Interaktif dengan Streamlit: dari DataFrame sampai Aplikasi Web
Dataset tabular menjadi jauh lebih berguna ketika stakeholder dapat memfilter dan menjelajahinya secara langsung. File CSV statis dan notebook Jupyter cukup untuk analisis internal, tetapi kedua format tersebut memaksa pembaca non-teknis untuk memahami kode. Dashboard web menyelesaikan masalah distribusi tersebut dengan menyajikan tabel, metrik, dan chart dalam satu halaman interaktif.
Streamlit adalah framework Python yang mengubah script analisis menjadi aplikasi web tanpa menulis HTML atau JavaScript. Framework tersebut membaca script dari atas ke bawah, me-render setiap panggilan st sebagai komponen UI, dan menjalankan ulang script setiap kali pengguna mengubah widget. Mari kita bangun dashboard penjualan dari nol dengan pendekatan tersebut.
Menyiapkan DataFrame sebagai Sumber Data Dashboard
Langkah pertama adalah memastikan DataFrame memiliki struktur yang konsisten sebelum ditampilkan. Dashboard yang baik membutuhkan kolom numerik untuk metrik, kolom kategorik untuk filter, dan kolom datetime untuk analisis tren. Struktur yang berantakan akan terbawa sampai ke UI dan membingungkan pengguna.
Kita mulai dengan membuat DataFrame contoh yang menyerupai data penjualan harian. Data tersebut mencakup tanggal, kota, kategori produk, dan nilai transaksi. Setelah loading, kita memeriksa lima baris pertama, info tipe data, dan statistik deskriptif untuk memastikan tidak ada tipe yang salah.
!pip install pandas
import pandas as pd
import numpy as np
np.random.seed(42)
tanggal = pd.date_range("2026-01-01", periods=90, freq="D")
df = pd.DataFrame({
"tanggal": np.tile(tanggal, 2),
"kota": np.repeat(["Jakarta", "Surabaya"], 90),
"kategori": np.random.choice(["Elektronik", "Fashion", "Makanan"], size=180),
"penjualan": np.random.randint(500_000, 5_000_000, size=180)
})
df["tanggal"] = pd.to_datetime(df["tanggal"])
df = df.dropna().reset_index(drop=True)
print(df.head())
print(df.info())
print(df.describe())Output:
tanggal kota kategori penjualan
0 2026-01-01 Jakarta Makanan 2735000
1 2026-01-02 Jakarta Elektronik 4822252
2 2026-01-03 Jakarta Makanan 902690
3 2026-01-04 Jakarta Makanan 3048421
4 2026-01-05 Jakarta Elektronik 4716263
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 180 entries, 0 to 179
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 tanggal 180 non-null datetime64[ns]
1 kota 180 non-null object
2 kategori 180 non-null object
3 penjualan 180 non-null int64
dtypes: datetime64[ns](1), int64(1), object(2)
memory usage: 5.8+ KB
tanggal penjualan
count 180 1.800000e+02
mean 2026-02-14 12:00:00 2.812712e+06
min 2026-01-01 00:00:00 5.393530e+05
25% 2026-01-23 00:00:00 1.718345e+06
50% 2026-02-14 12:00:00 2.733330e+06
75% 2026-03-09 00:00:00 3.944407e+06
max 2026-03-31 00:00:00 4.979125e+06
std NaN 1.343516e+06Logika pada kode di atas berfokus pada validasi awal. Fungsi head() menunjukkan bentuk data, info() memastikan tipe datetime terbaca benar, dan describe() memberikan gambaran distribusi nilai penjualan. Workflow validasi tersebut mencegah error rendering di tahap berikutnya, misalnya chart kosong karena kolom tanggal masih bertipe string.
Membangun Layout Dashboard dengan Komponen Streamlit
Setelah data valid, kita merancang layout dashboard. Struktur minimal terdiri dari judul, tiga metrik ringkas, dan tabel data. Metrik ringkas memberikan angka kunci dalam sekali pandang, sedangkan tabel memberikan detail mentah untuk verifikasi.
Perhitungan metrik dilakukan murni dengan Pandas sebelum ditampilkan. Total penjualan, rata-rata transaksi harian, dan jumlah transaksi adalah tiga angka yang paling sering dicari stakeholder. Kode berikut menghitung ketiga nilai tersebut dari DataFrame yang sama.
total_penjualan = df["penjualan"].sum()
rata_rata_harian = df.groupby("tanggal")["penjualan"].sum().mean()
jumlah_transaksi = len(df)
print(f"Total penjualan: Rp{total_penjualan:,}")
print(f"Rata-rata harian: Rp{rata_rata_harian:,.0f}")
print(f"Jumlah transaksi: {jumlah_transaksi}")Output:
Total penjualan: Rp506,288,245
Rata-rata harian: Rp5,625,425
Jumlah transaksi: 180Hasil perhitungan tersebut kemudian dipetakan ke komponen Streamlit. Nilai total_penjualan ditampilkan dengan st.metric, rata_rata_harian menjadi metrik kedua, dan jumlah_transaksi menjadi metrik ketiga dalam satu baris st.columns. Tabel data ditampilkan dengan st.dataframe yang mendukung sorting dan search bawaan.

Gambar: Contoh dashboard analitik yang menampilkan chart dan metrik pada layar laptop — Sumber: Unsplash - Carlos Muza
File aplikasi disimpan sebagai app.py dan dijalankan dengan satu perintah.
streamlit run app.py
Data Science with Python
Master the art of data analysis, visualization, and predictive modeling.
Perintah tersebut memulai server lokal di http://localhost:8501. Setiap perubahan pada widget akan memicu re-run script dari atas ke bawah sehingga angka selalu konsisten dengan filter aktif.
Mental model re-run perlu dipahami agar dashboard tetap cepat. Streamlit mengeksekusi ulang seluruh script dari baris pertama setiap kali state widget berubah. Variabel yang dihitung dari DataFrame terfilter akan selalu segar tanpa callback manual. Konsekuensinya, operasi berat seperti loading CSV dan agregasi besar sebaiknya dipindahkan ke fungsi ber-cache. Operasi ringan seperti masking boolean dan perhitungan metrik boleh tetap di alur utama karena dieksekusi dalam milidetik.
Menambahkan Visualisasi Interaktif dengan Chart Bawaan
Angka ringkas tidak cukup untuk melihat pola. Kita membutuhkan chart tren untuk melihat pergerakan waktu dan chart perbandingan untuk melihat kontribusi tiap kategori. Streamlit menyediakan chart cepat tanpa konfigurasi, plus dukungan penuh untuk figure Matplotlib.
Workflow visualisasi dimulai dari agregasi Pandas. Data harian diagregasi per tanggal untuk tren, lalu diagregasi per kategori untuk perbandingan. Hasil agregasi tersebut yang diumpankan ke chart, bukan DataFrame mentah. Pendekatan tersebut menjaga chart tetap cepat walau data membesar.
!pip install pandas matplotlib
import pandas as pd
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
np.random.seed(42)
tanggal = pd.date_range("2026-01-01", periods=90, freq="D")
df = pd.DataFrame({
"tanggal": np.tile(tanggal, 2),
"kota": np.repeat(["Jakarta", "Surabaya"], 90),
"kategori": np.random.choice(["Elektronik", "Fashion", "Makanan"], size=180),
"penjualan": np.random.randint(500_000, 5_000_000, size=180)
})
tren_harian = df.groupby("tanggal")["penjualan"].sum()
per_kategori = df.groupby("kategori")["penjualan"].sum().sort_values()
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
tren_harian.plot(ax=axes[0])
axes[0].set_title("Tren Penjualan Harian")
axes[0].set_xlabel("Tanggal")
axes[0].set_ylabel("Penjualan (Rp)")
per_kategori.plot(kind="barh", ax=axes[1])
axes[1].set_title("Total Penjualan per Kategori")
axes[1].set_xlabel("Penjualan (Rp)")
plt.tight_layout()
plt.savefig("/tmp/blog-chart-preview.png", dpi=150, bbox_inches="tight")
print(tren_harian.head())
print(per_kategori)Output:
tanggal
2026-01-01 6318153
2026-01-02 8121739
2026-01-03 4307631
2026-01-04 5648442
2026-01-05 6577091
Name: penjualan, dtype: int64
kategori
Fashion 152528029
Elektronik 163303128
Makanan 190457088
Name: penjualan, dtype: int64
Logika pada kode di atas memisahkan agregasi dan rendering. Agregasi menentukan cerita yang ingin disampaikan, sedangkan rendering hanya menampilkan hasil agregasi. Pemisahan tersebut memudahkan debugging karena kita dapat memeriksa tabel agregasi sebelum menyalahkan chart. Di Streamlit, figure Matplotlib yang sama ditampilkan dengan st.pyplot(fig), sedangkan tren cepat dapat menggunakan st.line_chart(tren_harian) tanpa Matplotlib.
Pemilihan chart mengikuti aturan sederhana. Tren waktu menggunakan line chart, perbandingan kategori menggunakan bar chart, dan distribusi nilai menggunakan histogram. Konsistensi tersebut membantu pengguna membaca dashboard baru dalam hitungan detik.
Menambahkan Filter Interaktif dengan Widget Sidebar
Dashboard statis cepat kehilangan relevansi karena setiap stakeholder memiliki pertanyaan berbeda. Filter sidebar menyelesaikan masalah tersebut dengan membiarkan pengguna memilih kota, kategori, dan rentang tanggal tanpa mengubah kode. Setiap perubahan widget memicu re-run dan seluruh angka serta chart diperbarui otomatis.
Mekanisme filter bekerja dalam tiga tahap. Pertama, widget membaca nilai pilihan pengguna. Kedua, DataFrame difilter dengan boolean masking Pandas. Ketiga, metrik dan chart dihitung ulang dari DataFrame terfilter. Tidak ada state manual yang perlu dikelola karena Streamlit menangani siklus tersebut.
import pandas as pd
import numpy as np
np.random.seed(42)
tanggal = pd.date_range("2026-01-01", periods=90, freq="D")
df = pd.DataFrame({
"tanggal": np.tile(tanggal, 2),
"kota": np.repeat(["Jakarta", "Surabaya"], 90),
"kategori": np.random.choice(["Elektronik", "Fashion", "Makanan"], size=180),
"penjualan": np.random.randint(500_000, 5_000_000, size=180)
})
df["tanggal"] = pd.to_datetime(df["tanggal"])
# Simulasi pilihan pengguna pada sidebar
kota_pilihan = ["Jakarta"]
kategori_pilihan = ["Elektronik", "Fashion"]
df_filtered = df[
df["kota"].isin(kota_pilihan) &
df["kategori"].isin(kategori_pilihan)
]
print(f"Data original: {len(df)} baris")
print(f"Data terfilter: {len(df_filtered)} baris")
print(df_filtered.groupby("kategori")["penjualan"].sum())Output:
Data original: 180 baris
Data terfilter: 61 baris
kategori
Elektronik 74463864
Fashion 98750521
Name: penjualan, dtype: int64Workflow pada kode di atas mencerminkan implementasi Streamlit yang sesungguhnya. Variabel kota_pilihan berasal dari st.sidebar.multiselect, sedangkan kategori_pilihan berasal dari widget serupa. Masking dengan isin menangani pilihan ganda secara natural. Output menunjukkan bahwa filter mengurangi baris secara signifikan dan agregasi berikutnya otomatis mengikuti subset tersebut.
Kasus kosong perlu ditangani secara eksplisit. Filter yang terlalu ketat dapat menghasilkan DataFrame kosong dan menyebabkan chart error. Solusinya adalah memeriksa df_filtered.empty sebelum rendering dan menampilkan pesan st.warning yang jelas.
Menerapkan Praktik Deployment dan Optimasi Performa Dashboard
Dashboard yang berjalan di laptop perlu dibagikan agar berguna. Streamlit Community Cloud memungkinkan deployment gratis langsung dari repository GitHub. File requirements.txt mendefinisikan dependensi agar environment cloud identik dengan environment lokal.
Caching adalah optimasi terpenting sebelum deployment. Tanpa caching, setiap interaksi widget memuat ulang CSV dari disk. Decorator @st.cache_data menyimpan hasil loading di memori sehingga re-run hanya mengeksekusi filter dan agregasi. Perbedaan latensi terasa jelas pada dataset di atas 100 ribu baris.

Gambar: Kode Python untuk aplikasi dashboard pada layar — Sumber: Unsplash
import time
import pandas as pd
import numpy as np
np.random.seed(42)
tanggal = pd.date_range("2026-01-01", periods=90, freq="D")
df = pd.DataFrame({
"tanggal": np.tile(tanggal, 2),
"kota": np.repeat(["Jakarta", "Surabaya"], 90),
"kategori": np.random.choice(["Elektronik", "Fashion", "Makanan"], size=180),
"penjualan": np.random.randint(500_000, 5_000_000, size=180)
})
# Simulasi fungsi cached vs non-cached
start = time.time()
hasil = df.groupby(["kota", "kategori"])["penjualan"].sum()
durasi = time.time() - start
print(hasil)
print(f"Agregasi selesai dalam {durasi:.4f} detik")
print(f"Cache aktif: hasil agregasi dapat dipakai ulang tanpa hitung ulang")Output:
kota kategori
Jakarta Elektronik 74463864
Fashion 98750521
Makanan 76148247
Surabaya Elektronik 88839264
Fashion 53777508
Makanan 114308841
Name: penjualan, dtype: int64
Agregasi selesai dalam 0.0015 detik
Cache aktif: hasil agregasi dapat dipakai ulang tanpa hitung ulangLogika pada kode di atas menunjukkan pola yang dibungkus @st.cache_data pada aplikasi nyata. Fungsi loader dan fungsi agregasi berat diberi decorator tersebut, sedangkan filter interaktif tetap dieksekusi setiap re-run. Workflow tersebut memberikan keseimbangan antara data segar dan respons cepat.
Checklist sebelum share mencakup tiga hal. File requirements.txt harus berisi streamlit, pandas, dan matplotlib dengan versi yang terkunci. Kondisi filter kosong harus menampilkan pesan yang informatif, bukan traceback. Dataset besar sebaiknya disampling atau diagregasi dulu agar loading awal di bawah lima detik.
Proses deployment sendiri cukup lugas. Kita push app.py dan requirements.txt ke repository GitHub, menghubungkan repository tersebut ke Streamlit Community Cloud, dan menentukan file utama sebagai entry point. Setiap push ke branch utama akan memicu redeploy otomatis. Praktik tersebut menjaga dashboard yang live selalu sinkron dengan versi data dan logika terbaru tanpa langkah manual tambahan.
Ingin memperdalam kemampuan building dashboard dan data analysis dengan Python? Rumah Coding menyediakan bootcamp Data Science yang mencakup Pandas, visualisasi data, dan deployment aplikasi. Kunjungi website kami untuk informasi lebih lanjut tentang program yang tersedia.
Course Terkait
Data Science with Python
Master the art of data analysis, visualization, and predictive modeling.
E-commerce Sales Dashboard
- Data Cleaning Pipeline
- Interactive Charts
- Sales Forecasting Model
Deep Learning Bootcamp
A beginner-friendly, highly interactive bootcamp designed to take you from foundational concepts to deploying real-world Artificial Intelligence applications. Through a completely project-based approach, you will master the core of Deep Learning, Artificial Neural Networks, and Computer Vision using Python and TensorFlow, ultimately building a professional-grade AI web application for your portfolio.
GreenGuard: Intelligent Plant Disease Diagnosis Web App
- Interactive Image Upload UI: A clean, user-friendly interface built with Streamlit that supports drag-and-drop image uploads directly from a computer or mobile phone.
- Real-Time AI Inference: Utilizes a lightweight, optimized CNN model (like MobileNetV2) to process the image and return a diagnosis in seconds without heavy server load.
- Confidence Scoring Dashboard: Visually displays the model's prediction probability (e.g., "95% confident this is Tomato Late Blight") using interactive progress bars or charts.
LLM Bootcamp
This project-based bootcamp is designed for beginners to dive practically into the world of Large Language Models (LLMs). Through hands-on building, you will learn how to interact with top-tier AI APIs, master prompt engineering, orchestrate complex workflows using LangChain, and implement Retrieval-Augmented Generation (RAG) to query your own documents. By the end of this course, you will have the skills to build, test, and deploy a fully functional, custom AI web application.
Domain-Specific AI Knowledge Assistant
- Dynamic Document Processing: A sidebar interface allowing users to upload new PDF or TXT files, which the app automatically chunks, embeds, and stores in the vector database.
- Context-Aware Chat UI: A modern chat interface built with Streamlit that maintains conversation history, allowing users to ask follow-up questions naturally.
- Strict Guardrails (Anti-Hallucination): System instructions designed so the AI politely declines to answer questions that fall outside the context of the uploaded documents.