Idenya
Dashboard menjadi aplikasi saat pembaca bisa mengajukan pertanyaan mereka sendiri: "hanya kategori Coffee", "order di atas Rp 500.000", "hanya channel app". Setiap widget adalah satu pertanyaan, dan berkat model rerun, memakai jawabannya hanyalah Python biasa: baca nilainya, filter DataFrame-nya, tampilkan hasilnya.
import pandas as pd
sales = pd.read_csv("sales.csv")
completed = sales[sales["status"] == "completed"]
Memilih satu opsi: selectbox dan radio
Hal pertama yang diinginkan sebagian besar pengguna dashboard adalah melihat satu potongan data, seperti satu kategori produk. Selectbox memberi mereka dropdown berisi pilihan, dan apa pun yang dipilih langsung menjadi nilai kembaliannya, siap dipakai untuk memfilter:
import streamlit as st
import pandas as pd
sales = pd.read_csv("sales.csv")
completed = sales[sales["status"] == "completed"]
categories = sorted(completed["category"].unique())
category = st.selectbox("Category", categories)
rows = completed[completed["category"] == category]
st.metric(f"{category} revenue", f"Rp {rows['revenue'].sum():,}")
st.dataframe(rows[["order_date", "product", "quantity", "revenue"]], hide_index=True)
- Argumen pertama adalah label yang ditampilkan di atas widget.
- Opsinya berasal dari data (
unique()), jadi kategori baru muncul secara otomatis. st.radiomelakukan hal yang sama dengan semua opsi terlihat sekaligus, bagus untuk 2 sampai 4 pilihan.
Untuk menawarkan "semuanya" sebagai pilihan, tambahkan ke opsi-opsinya:
import streamlit as st
options = ["All"] + ["Coffee", "Electronics", "Home"]
choice = st.radio("Show", options, horizontal=True)
st.write("You picked", choice)
Memilih beberapa: multiselect
Kadang pengguna ingin lebih dari satu opsi sekaligus, seperti kedua channel penjualan atau salah satunya saja. Multiselect memungkinkan mereka memilih berapa pun:
import streamlit as st
import pandas as pd
sales = pd.read_csv("sales.csv")
completed = sales[sales["status"] == "completed"]
channels = st.multiselect("Channels", ["web", "app"], default=["web", "app"])
rows = completed[completed["channel"].isin(channels)]
st.write(f"{rows['order_id'].nunique()} orders from {', '.join(channels) or 'no channel'}")
Multiselect mengembalikan list. isin langsung mengubahnya menjadi filter. Perhatikan kasus kosong: kalau pengguna menghapus semua channel, list-nya kosong dan begitu juga hasilnya. Tentukan apa yang seharusnya ditampilkan untuk itu.
Angka: slider dan number_input
Untuk filter angka, seperti "hanya tampilkan baris pesanan yang nilainya minimal sekian", slider lebih cepat dipakai daripada mengetik angka:
import streamlit as st
import pandas as pd
sales = pd.read_csv("sales.csv")
completed = sales[sales["status"] == "completed"]
min_revenue = st.slider("Minimum line revenue (Rp)", 0, 1_000_000, 100_000, step=50_000)
big = completed[completed["revenue"] >= min_revenue]
st.write(f"{len(big)} order lines of at least Rp {min_revenue:,}")
st.slider(label, min, max, default, step=...). Beri tuple sebagai default dan ia menjadi range slider yang mengembalikan (low, high):
import streamlit as st
low, high = st.slider("Price range (thousand Rp)", 0, 400, (50, 200))
st.write(f"Between {low} and {high}")
st.number_input adalah kotak dengan tombol + dan −, lebih baik saat pengguna tahu angka persisnya (quantity, target).
Teks: text_input
Kotak pencarian memungkinkan pengguna menemukan produk berdasarkan nama tanpa menggulir seluruh tabel:
import streamlit as st
import pandas as pd
sales = pd.read_csv("sales.csv")
search = st.text_input("Search products", placeholder="e.g. coffee")
if search:
hits = sales[sales["product"].str.contains(search, case=False)]
st.write(f"{hits['product'].nunique()} matching products")
st.dataframe(hits[["product", "category"]].drop_duplicates(), hide_index=True)
Kotak teks yang kosong mengembalikan "", jadi if search: hanya memfilter setelah pengguna mengetik. case=False membuat pencariannya tidak membedakan huruf besar-kecil.
Key: memberi nama widget
Setiap widget diidentifikasi oleh label-nya. Dua widget dengan label yang sama membingungkan Streamlit:
import streamlit as st
start = st.date_input("Date")
end = st.date_input("Date")
Streamlit berhenti dengan error: There are multiple identical st.date_input widgets with the same generated key. Beri masing-masing key= yang unik (dan label yang lebih baik):
import streamlit as st
start = st.date_input("From", key="start_date")
end = st.date_input("To", key="end_date")
Key menjadi penting bersama st.session_state, dua modul dari sekarang.
Menggabungkan filter
Aplikasi sungguhan merangkai beberapa widget menjadi satu DataFrame hasil filter:
import streamlit as st
import pandas as pd
sales = pd.read_csv("sales.csv")
completed = sales[sales["status"] == "completed"]
category = st.selectbox("Category", ["All"] + sorted(completed["category"].unique()))
channels = st.multiselect("Channels", ["web", "app"], default=["web", "app"])
rows = completed[completed["channel"].isin(channels)]
if category != "All":
rows = rows[rows["category"] == category]
st.metric("Revenue", f"Rp {rows['revenue'].sum():,}")
st.dataframe(rows, hide_index=True)
Baca input dulu, filter langkah demi langkah, lalu tampilkan. Saat logika filter-nya bertambah, pindahkan ke sebuah fungsi filter_sales(df, category, channels) yang bisa kamu uji tanpa Streamlit.
Mengapa ini penting untuk kode yang bersih
Widget adalah input pengguna, jadi semua aturan input berlaku: beri label yang jelas, ambil opsi dari data, tangani kasus kosong, dan simpan logika filter di fungsi biasa. Aplikasi yang filternya tinggal di satu fungsi teruji mudah diubah; aplikasi yang filternya tersebar di antara pemanggilan widget tidak.
Rangkuman
st.selectbox/st.radiomemilih satu;st.multiselectmemilih sebuah list (pakaiisin).st.slider(label, min, max, default); default berupa tuple membuat range slider.st.number_inputuntuk angka persis;st.text_inputmengembalikan""saat kosong.- Ambil opsi dari data; tambahkan
"All"saat perlu; tangani pilihan yang kosong. - Label yang dobel butuh nilai
key=yang unik. - Baca input → filter → tampilkan; taruh logika filter di fungsi yang bisa diuji.