快轉到主要內容
  1. 教學文章/

Streamlit:用 Python 快速打造互動式資料應用

·8 分鐘· loading · loading · ·
Python Streamlit Data-Visualization Web-App Dashboard
每日拍拍
作者
每日拍拍
科學家 X 科技宅宅
目錄
Python 學習 - 本文屬於一個選集。
§ 21: 本文

一. 前言
#

你有沒有過這樣的經驗:用 Python 辛辛苦苦做完資料分析,結果只能在 Jupyter Notebook 裡面看?想分享給同事或主管,卻發現他們根本不想打開終端機?🤦

拍拍君今天要介紹一個超強的工具 —— Streamlit!它讓你用純 Python 就能快速打造出漂亮的互動式 Web 應用,不用寫一行 HTML、CSS 或 JavaScript。資料科學家最愛的秘密武器,學完今天的教學你就懂了!

二. 安裝
#

用 pip 或 uv 都可以輕鬆安裝:

# pip 安裝
pip install streamlit

# 或用 uv(推薦,超快!)
uv pip install streamlit

安裝完成後,確認一下版本:

streamlit --version

想要快速看看 Streamlit 能幹嘛?跑一下官方 demo:

streamlit hello

瀏覽器會自動打開,展示幾個互動式範例。是不是很酷?😎

三. 第一個 Streamlit App
#

建立一個 app.py

import streamlit as st

st.title("🎉 拍拍君的第一個 Streamlit App")
st.write("歡迎來到每日拍拍的 Streamlit 教學!")

name = st.text_input("你的名字是?")
if name:
    st.write(f"哈囉,{name}!很高興認識你 👋")

啟動它:

streamlit run app.py

瀏覽器自動開啟 http://localhost:8501,你就能看到一個有文字輸入框的互動頁面了。每次修改 app.py 存檔後,頁面會自動重新載入,開發體驗超棒!

Streamlit 的核心概念
#

Streamlit 的運作方式很特別:每次使用者互動,整個 script 會從頭到尾重新執行一次。這意味著你不用管什麼 callback 或事件監聽,直接用 Python 的 if-else 就能處理互動邏輯。簡單粗暴,但超級有效。

四. 常用元件速覽
#

Streamlit 提供了豐富的 UI 元件,讓我們快速看幾個最常用的:

文字顯示
#

import streamlit as st

st.title("標題")          # 大標題
st.header("次標題")       # 次標題
st.subheader("小標題")    # 小標題
st.text("純文字")         # 純文字
st.markdown("**粗體** 和 *斜體*")  # Markdown
st.code("print('hello')", language="python")  # 程式碼
st.latex(r"E = mc^2")    # LaTeX 公式

輸入元件
#

# 文字輸入
name = st.text_input("姓名")

# 數字滑桿
age = st.slider("年齡", 0, 100, 25)

# 下拉選單
lang = st.selectbox("最愛的語言", ["Python", "Rust", "Go", "TypeScript"])

# 多選
skills = st.multiselect("你會的技能", ["ML", "Web", "Data", "DevOps"])

# 核取方塊
agree = st.checkbox("我同意使用條款")

# 按鈕
if st.button("送出"):
    st.write("已送出!✅")

資料顯示
#

import pandas as pd

df = pd.DataFrame({
    "名字": ["拍拍君", "拍拍醬", "chatPTT"],
    "分數": [95, 87, 92],
    "等級": ["A+", "A", "A"],
})

st.dataframe(df)          # 互動式表格(可排序、搜尋)
st.table(df)              # 靜態表格
st.metric("今日訪客", "1,234", "+56")  # 指標卡片

五. 資料視覺化
#

Streamlit 和主流繪圖套件完美整合,畫圖超級方便:

內建圖表
#

import streamlit as st
import pandas as pd
import numpy as np

# 產生假資料
chart_data = pd.DataFrame(
    np.random.randn(30, 3),
    columns=["Python", "Rust", "Go"]
)

st.line_chart(chart_data)    # 折線圖
st.bar_chart(chart_data)     # 長條圖
st.area_chart(chart_data)    # 面積圖

搭配 Plotly(互動式圖表)
#

如果你需要更精細的圖表控制,可以搭配 Plotly:

uv pip install plotly
import streamlit as st
import plotly.express as px
import pandas as pd

df = pd.DataFrame({
    "月份": ["一月", "二月", "三月", "四月", "五月", "六月"],
    "營收": [120, 150, 180, 160, 200, 220],
    "成本": [80, 90, 100, 95, 110, 120],
})

fig = px.bar(df, x="月份", y=["營收", "成本"], barmode="group",
             title="拍拍公司月報表")
st.plotly_chart(fig, use_container_width=True)

這樣就能得到一個可以 hover、zoom 的互動式長條圖!

搭配 Matplotlib
#

習慣用 Matplotlib 的朋友也沒問題:

import streamlit as st
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
ax.legend()
ax.set_title("三角函數圖")

st.pyplot(fig)

六. 版面配置與進階功能
#

Sidebar(側邊欄)
#

把控制項放到側邊欄,讓主畫面保持乾淨:

import streamlit as st

st.sidebar.title("⚙️ 設定")
dataset = st.sidebar.selectbox("選擇資料集", ["iris", "titanic", "wine"])
show_raw = st.sidebar.checkbox("顯示原始資料", value=False)

st.title(f"📊 {dataset} 資料分析")
if show_raw:
    st.write("這裡顯示原始資料...")

Columns(多欄排版)
#

import streamlit as st

col1, col2, col3 = st.columns(3)

with col1:
    st.metric("CPU", "45%", "-5%")

with col2:
    st.metric("Memory", "72%", "+3%")

with col3:
    st.metric("Disk", "60%", "+1%")

Tabs(分頁)
#

import streamlit as st

tab1, tab2, tab3 = st.tabs(["📈 圖表", "📋 資料", "🔧 設定"])

with tab1:
    st.write("這裡放圖表")

with tab2:
    st.write("這裡放資料表格")

with tab3:
    st.write("這裡放設定選項")

Expander(展開收合)
#

import streamlit as st

with st.expander("💡 點我看進階說明"):
    st.write("這段文字預設是隱藏的,點擊標題才會展開。")
    st.code("print('隱藏的秘密 🤫')")

七. Session State:記住使用者狀態
#

前面提到 Streamlit 每次互動都會重跑整個 script,那要怎麼記住狀態呢?答案是 st.session_state

import streamlit as st

# 初始化計數器
if "count" not in st.session_state:
    st.session_state.count = 0

# 按鈕操作
col1, col2 = st.columns(2)
with col1:
    if st.button("➕ 加一"):
        st.session_state.count += 1
with col2:
    if st.button("🔄 歸零"):
        st.session_state.count = 0

st.write(f"目前計數:**{st.session_state.count}**")

session_state 是每個使用者 session 獨立的,不同使用者之間不會互相干擾。這在做登入系統或多步驟表單時超級好用!

八. 實戰:打造 CSV 分析儀表板
#

讓我們結合前面學的東西,做一個完整的小專案:

import streamlit as st
import pandas as pd
import plotly.express as px

st.set_page_config(page_title="📊 拍拍君的 CSV 分析器", layout="wide")
st.title("📊 拍拍君的 CSV 分析器")
st.write("上傳一個 CSV 檔案,拍拍君幫你分析!")

uploaded_file = st.file_uploader("選擇 CSV 檔案", type="csv")

if uploaded_file is not None:
    df = pd.read_csv(uploaded_file)

    # 基本資訊
    st.header("📋 資料概覽")
    col1, col2, col3 = st.columns(3)
    with col1:
        st.metric("筆數", f"{len(df):,}")
    with col2:
        st.metric("欄位數", len(df.columns))
    with col3:
        st.metric("缺失值", int(df.isnull().sum().sum()))

    # 資料預覽
    with st.expander("🔍 查看前 10 筆資料"):
        st.dataframe(df.head(10))

    # 統計摘要
    with st.expander("📊 統計摘要"):
        st.dataframe(df.describe())

    # 視覺化
    st.header("📈 視覺化")
    numeric_cols = df.select_dtypes(include="number").columns.tolist()

    if len(numeric_cols) >= 2:
        col1, col2 = st.columns(2)
        with col1:
            x_col = st.selectbox("X 軸", numeric_cols, index=0)
        with col2:
            y_col = st.selectbox("Y 軸", numeric_cols, index=min(1, len(numeric_cols)-1))

        chart_type = st.radio("圖表類型", ["散佈圖", "折線圖", "長條圖"], horizontal=True)

        if chart_type == "散佈圖":
            fig = px.scatter(df, x=x_col, y=y_col, title=f"{x_col} vs {y_col}")
        elif chart_type == "折線圖":
            fig = px.line(df, x=x_col, y=y_col, title=f"{x_col} vs {y_col}")
        else:
            fig = px.bar(df, x=x_col, y=y_col, title=f"{x_col} vs {y_col}")

        st.plotly_chart(fig, use_container_width=True)
    else:
        st.info("需要至少兩個數值欄位才能畫圖 📉")
else:
    st.info("👆 請上傳一個 CSV 檔案開始分析")

存成 csv_analyzer.py,然後 streamlit run csv_analyzer.py 就能用了!

九. 部署到 Streamlit Community Cloud
#

寫好 app 之後,最棒的是可以免費部署到 Streamlit Community Cloud

  1. 把程式碼推到 GitHub repo
  2. 在 repo 根目錄加一個 requirements.txt
streamlit
pandas
plotly
  1. share.streamlit.io 登入你的 GitHub
  2. 選擇 repo、branch、主檔案路徑
  3. 點 Deploy!

幾分鐘後你的 app 就上線了,會得到一個 https://xxx.streamlit.app 的網址,直接分享給任何人!完全免費,小型專案超夠用。

💡 小提醒:如果需要 secrets(API key 之類的),可以用 Streamlit Cloud 的 Secrets 管理功能,不要直接寫在程式碼裡喔。

結語
#

Streamlit 真的是 Python 開發者的大福音!不用學前端框架,就能把資料分析成果變成漂亮的互動式應用。拍拍君覺得它特別適合:

  • 🔬 資料科學的 prototype 和 demo
  • 📊 內部使用的 dashboard
  • 🤖 LLM/ML 模型的展示介面
  • 📝 快速驗證想法的 MVP

今天介紹的只是冰山一角,Streamlit 還有 st.cache_data 快取、多頁面 app、自訂元件等進階功能。掌握基礎之後,探索起來就很順了!

趕快去試試看吧,做一個屬於自己的資料儀表板 🚀

延伸閱讀
#

Python 學習 - 本文屬於一個選集。
§ 21: 本文

相關文章

Python Logging:別再 print 了,用正經的方式記錄日誌吧
·6 分鐘· loading · loading
Python Logging Debug 標準庫
Polars:比 Pandas 快 10 倍的 DataFrame 新選擇
·6 分鐘· loading · loading
Python Polars Dataframe 資料分析 Rust
PyTorch 神經網路入門:從零開始建立你的第一個模型
·5 分鐘· loading · loading
Python Pytorch Neural-Network Deep-Learning Machine-Learning
Ruff:用 Rust 寫的 Python Linter,快到你會懷疑人生
·4 分鐘· loading · loading
Python Ruff Linter Formatter Code-Quality
Pre-commit Hooks:讓壞 Code 連 Commit 的機會都沒有
·4 分鐘· loading · loading
Python Pre-Commit Git Linter Code-Quality Ruff Mypy
少寫一半程式碼:dataclasses 讓你的 Python 類別煥然一新
·6 分鐘· loading · loading
Python Dataclasses Oop 標準庫