Dash 分析仪表盘
Dash 是 Plotly 官方出品的 Python Web 仪表盘框架,基于 Flask + React + Plotly.js,用回调机制实现交互,适合构建生产级的企业数据分析应用,是 Python 仪表盘框架中功能最强大的选择。
核心知识点
| 知识点 | 说明 |
|---|
| 工具定位 | Python 企业级数据仪表盘框架 |
| 最新版本 | Dash 3.3.0 / Dash 4.x(2026 年) |
| 开发团队 | Plotly 公司 |
| 核心优势 | 回调机制精细控制、Plotly 图表原生支持、企业级 |
| 技术栈 | Python + Flask + React + Plotly.js |
| 企业版 | Dash Enterprise(付费,含部署/认证/监控) |
安装配置
# pip 安装
pip install dash # 安装 Dash(含 dash-core-components 等)
pip install pandas plotly # 数据处理和图表
# 可选组件
pip install dash-bootstrap-components # Bootstrap 样式组件
pip install dash-ag-grid # AG Grid 高性能表格
基本使用
1. 第一个 Dash 应用
from dash import Dash, html, dcc # 导入 Dash 核心组件
import plotly.express as px # 导入 Plotly Express
import pandas as pd # 导入 Pandas
# 创建应用
app = Dash(__name__) # 创建 Dash 实例
# 准备数据
df = pd.DataFrame({
"物种": ["Bacteroidetes", "Firmicutes", "Proteobacteria",
"Actinobacteria", "Fusobacteria"],
"丰度": [35, 28, 15, 12, 10]
})
# 创建图表
fig = px.bar(df, x="物种", y="丰度", title="物种丰度分布")
# 布局(类似 HTML 结构)
app.layout = html.Div([ # 最外层 div
html.H1("🧬 菌群分析仪表盘"), # 标题
html.P("基于 Dash 构建的交互式分析工具"), # 描述
dcc.Graph(figure=fig) # Plotly 图表组件
])
# 启动
if __name__ == "__main__":
app.run(debug=True) # 启动开发服务器
# 访问 http://localhost:8050
2. 回调机制(Dash 的核心)
from dash import Dash, html, dcc, callback, Input, Output # 导入回调
app = Dash(__name__)
# 布局
app.layout = html.Div([
html.H1("交互式分析"),
dcc.Dropdown( # 下拉菜单
id="group-dropdown", # 组件 ID(回调用)
options=[ # 选项
{"label": "健康组", "value": "健康"},
{"label": "疾病组", "value": "疾病"},
{"label": "全部", "value": "全部"}
],
value="全部" # 默认值
),
dcc.Graph(id="abundance-chart") # 图表占位
])
# 回调:下拉菜单变化 → 图表更新
@callback(
Output("abundance-chart", "figure"), # 输出:图表的 figure 属性
Input("group-dropdown", "value") # 输入:下拉菜单的值
)
def update_chart(selected_group):
"""根据选择的组别更新图表"""
if selected_group == "全部":
filtered = df # 不过滤
else:
filtered = df[df["组别"] == selected_group] # 按组过滤
fig = px.bar(filtered, x="物种", y="丰度",
title=f"{selected_group} - 物种丰度")
return fig # 返回新图表
if __name__ == "__main__":
app.run(debug=True)
3. 多输入多输出
from dash import Dash, html, dcc, callback, Input, Output, State
@callback(
[Output("chart", "figure"), # 输出 1:图表
Output("summary", "children")], # 输出 2:文本
[Input("group-dd", "value"), # 输入 1:组别
Input("chart-type", "value")], # 输入 2:图表类型
[State("threshold", "value")] # 状态(不触发回调,只读取值)
)
def update_all(group, chart_type, threshold):
"""多输入多输出的回调"""
filtered = df[df["丰度"] > threshold] # 用阈值过滤
if chart_type == "bar":
fig = px.bar(filtered, x="物种", y="丰度")
else:
fig = px.pie(filtered, values="丰度", names="物种")
summary = f"共 {len(filtered)} 个物种,阈值 {threshold}"
return fig, summary # 返回多个输出
高级用法
1. Bootstrap 样式(美化界面)
from dash import Dash, html, dcc
import dash_bootstrap_components as dbc # Bootstrap 组件
# 使用 Bootstrap 主题
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container([ # Bootstrap 容器
dbc.Row([ # 行
dbc.Col([ # 列(左侧控件)
dbc.Card([ # 卡片
dbc.CardHeader("参数设置"),
dbc.CardBody([
dbc.Label("选择组别"),
dcc.Dropdown(id="group-dd",
options=["健康", "疾病"]),
html.Br(),
dbc.Label("阈值"),
dcc.Slider(id="threshold",
min=0, max=100, value=50),
])
])
], width=3), # 占 3/12 宽度
dbc.Col([ # 列(右侧图表)
dcc.Graph(id="main-chart")
], width=9) # 占 9/12 宽度
])
], fluid=True) # 全宽布局
2. 多页面应用(Pages)
# Dash Pages:自动多页面路由
# 文件结构:
# app.py
# pages/
# home.py
# analysis.py
# about.py
# app.py
from dash import Dash, html, dcc, page_container
app = Dash(__name__, use_pages=True) # 启用 Pages
app.layout = html.Div([
html.H1("菌群分析平台"),
html.Div([ # 导航链接
dcc.Link("首页", href="/"),
dcc.Link("分析", href="/analysis"),
dcc.Link("关于", href="/about"),
]),
page_container # 页面内容在这里渲染
])
# pages/home.py
from dash import register_page, html
register_page(__name__, path="/") # 注册页面路由
layout = html.Div([html.H2("欢迎使用")])
# pages/analysis.py
from dash import register_page, html, dcc
register_page(__name__, path="/analysis")
layout = html.Div([
html.H2("数据分析"),
dcc.Graph(id="analysis-chart")
])
3. 数据表格(AG Grid)
from dash import Dash, html
import dash_ag_grid as dag # 高性能表格
app.layout = html.Div([
dag.AgGrid(
id="data-table",
rowData=df.to_dict("records"), # 数据
columnDefs=[ # 列定义
{"field": "物种", "filter": True, "sortable": True},
{"field": "丰度", "filter": "agNumberColumnFilter"},
{"field": "组别", "filter": True},
],
defaultColDef={"resizable": True}, # 可调整列宽
dashGridOptions={"pagination": True, "paginationPageSize": 20}
)
])
4. 部署
# 使用 gunicorn 部署(生产环境)
pip install gunicorn
gunicorn app:server --bind 0.0.0.0:8050 --workers 4
# Docker 部署
# Dockerfile
FROM python:3.12-slim
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . /app
WORKDIR /app
CMD ["gunicorn", "app:server", "--bind", "0.0.0.0:8050"]
常见报错与解决
| 报错信息 | 原因 | 解决方法 |
|---|
Callback ID not found | Output/Input 的 id 写错 | 检查组件 id 拼写 |
| 回调不触发 | 组件没有在布局中 | 确保所有回调用到的组件都在 layout 里 |
| 循环回调错误 | Output 又是另一个回调的 Input | 拆分回调或用 State |
| 页面加载慢 | 数据量大 | 分页、采样或用 AG Grid |
速查表
# ===== Dash 速查表 =====
from dash import Dash, html, dcc, callback, Input, Output
# 创建应用
app = Dash(__name__)
app.layout = html.Div([...])
app.run(debug=True)
# HTML 组件
html.Div(), html.H1(), html.P(), html.Br()
html.Button("点击", id="btn")
# 核心组件
dcc.Graph(id="chart") # Plotly 图表
dcc.Dropdown(id="dd") # 下拉菜单
dcc.Slider(id="slider") # 滑块
dcc.Input(id="input") # 文本输入
dcc.Checklist() # 复选框组
dcc.RadioItems() # 单选按钮组
dcc.Upload() # 文件上传
dcc.Tabs() # 标签页
# 回调
@callback(Output("id", "prop"), Input("id", "prop"))
def update(value): return result
# 部署
gunicorn app:server --bind 0.0.0.0:8050
# Dash vs Streamlit
# Dash: 回调机制,精细控制,企业级,学习曲线高
# Streamlit: rerun 模式,简单快速,适合原型
# 建议:快速原型用 Streamlit,生产应用用 Dash