静态图表不够直观,交互式仪表盘才是数据分析的利器。本文对比Streamlit、Dash、Plotly,并用Streamlit快速搭建数据分析应用。
一、三种方案对比
| 框架 | 特点 | 适合 |
|---|---|---|
| Streamlit | 极简,脚本式 | 快速原型、数据应用 |
| Dash | 基于Flask+React | 复杂仪表盘 |
| Plotly | 图表库 | 交互图表 |
二、Streamlit快速入门
bash
复制
下载
pip install streamlit plotly pandas
python
复制
下载
# app.py import streamlit as st import pandas as pd import plotly.express as px st.title("销售数据分析") # 侧边栏 st.sidebar.header("筛选条件") city = st.sidebar.selectbox("城市", ["全部", "北京", "上海", "广州"]) date_range = st.sidebar.date_input("日期范围") # 数据 @st.cache_data def load_data(): return pd.read_csv("sales.csv", parse_dates=["date"]) df = load_data() # 筛选 if city != "全部": df = df[df["city"] == city] # 指标 col1, col2, col3 = st.columns(3) col1.metric("总销售额", f"¥{df['amount'].sum():,.0f}") col2.metric("订单数", len(df)) col3.metric("客单价", f"¥{df['amount'].mean():.2f}") # 图表 fig = px.line(df.groupby("date")["amount"].sum().reset_index(), x="date", y="amount", title="销售趋势") st.plotly_chart(fig, use_container_width=True) # 数据表 st.subheader("原始数据") st.dataframe(df.head(100))运行:
bash
复制
下载
streamlit run app.py
三、Streamlit核心组件
python
复制
下载
import streamlit as st # 文本 st.title("标题") st.header("二级标题") st.subheader("三级标题") st.write("普通文本") st.markdown("**加粗** _斜体_") st.code("print('hello')", language="python") st.latex(r"E = mc^2") # 输入 name = st.text_input("姓名") age = st.number_input("年龄", min_value=0, max_value=120) agree = st.checkbox("同意") level = st.slider("等级", 1, 10, 5) choice = st.radio("选择", ["A", "B", "C"]) multi = st.multiselect("多选", ["x", "y", "z"]) file = st.file_uploader("上传文件", type=["csv", "xlsx"]) # 布局 col1, col2 = st.columns(2) with col1: st.write("左列") with col2: st.write("右列") with st.expander("展开详情"): st.write("隐藏内容") tab1, tab2 = st.tabs(["标签1", "标签2"]) with tab1: st.write("内容1") # 状态 if "count" not in st.session_state: st.session_state.count = 0 if st.button("+1"): st.session_state.count += 1 st.write(f"计数: {st.session_state.count}") # 进度 import time progress = st.progress(0) for i in range(100): time.sleep(0.01) progress.progress(i + 1)四、Plotly交互图表
python
复制
下载
import plotly.express as px import plotly.graph_objects as go # 折线图 fig = px.line(df, x="date", y="amount", color="city", title="各城市销售趋势") fig.show() # 柱状图 fig = px.bar(df, x="city", y="amount", color="category", barmode="group") # 散点图 fig = px.scatter(df, x="price", y="sales", size="quantity", color="category", hover_data=["name"]) # 饼图 fig = px.pie(df, names="category", values="amount") # 热力图 fig = px.imshow(correlation_matrix, text_auto=True) # 3D fig = px.scatter_3d(df, x="x", y="y", z="z", color="category") # 地图 fig = px.scatter_mapbox(df, lat="lat", lon="lon", size="value", color="category", mapbox_style="open-street-map") # 自定义 fig = go.Figure() fig.add_trace(go.Scatter(x=[1,2,3], y=[4,5,6], mode='lines+markers')) fig.update_layout(title="自定义图表", xaxis_title="X", yaxis_title="Y")
五、Dash入门
python
复制
下载
from dash import Dash, dcc, html, Input, Output import plotly.express as px app = Dash(__name__) app.layout = html.Div([ html.H1("Dash仪表盘"), dcc.Dropdown( id="city-dropdown", options=[{"label": c, "value": c} for c in df["city"].unique()], value=df["city"].unique()[0] ), dcc.Graph(id="sales-graph"), ]) @app.callback( Output("sales-graph", "figure"), Input("city-dropdown", "value") ) def update_graph(city): filtered = df[df["city"] == city] fig = px.line(filtered, x="date", y="amount") return fig if __name__ == "__main__": app.run_server(debug=True)六、实战:股票分析仪表盘
python
复制
下载
import streamlit as st import yfinance as yf import plotly.graph_objects as go st.set_page_config(page_title="股票分析", layout="wide") st.title("📈 股票分析仪表盘") # 输入 ticker = st.sidebar.text_input("股票代码", "AAPL") period = st.sidebar.selectbox("周期", ["1mo", "3mo", "6mo", "1y", "5y"]) # 数据 @st.cache_data(ttl=300) def get_stock(ticker, period): return yf.Ticker(ticker).history(period=period) data = get_stock(ticker, period) if not data.empty: # 指标 col1, col2, col3, col4 = st.columns(4) current = data["Close"].iloc[-1] prev = data["Close"].iloc[-2] change = (current - prev) / prev * 100 col1.metric("当前价", f"${current:.2f}", f"{change:+.2f}%") col2.metric("最高", f"${data['High'].max():.2f}") col3.metric("最低", f"${data['Low'].min():.2f}") col4.metric("成交量", f"{data['Volume'].sum():,.0f}") # K线图 fig = go.Figure(data=[go.Candlestick( x=data.index, open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'] )]) fig.update_layout(title=f"{ticker} K线图", xaxis_rangeslider_visible=False) st.plotly_chart(fig, use_container_width=True) # 成交量 fig2 = px.bar(data, x=data.index, y="Volume", title="成交量") st.plotly_chart(fig2, use_container_width=True)七、部署
7.1 Streamlit Cloud
推送代码到GitHub,访问 share.streamlit.io 一键部署。
7.2 Docker
dockerfile
复制
下载
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 8501 CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
7.3 Nginx反向代理
nginx
复制
下载
location / { proxy_pass http://localhost:8501; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }八、性能优化
python
复制
下载
# 缓存数据 @st.cache_data def load_data(): return pd.read_csv("big.csv") # 缓存资源 @st.cache_resource def get_model(): return load_ml_model() # 分页 page = st.number_input("页码", 1, 100) st.dataframe(df.iloc[(page-1)*100:page*100])九、总结
Streamlit适合快速搭建数据应用,Dash适合复杂仪表盘,Plotly提供丰富交互图表。三者结合,能快速交付数据分析产品。推荐新项目优先用Streamlit + Plotly。