3.4.4 交互式可视化
- 理解静态图 vs 交互图的区别
- 掌握 Plotly Express 快速绑图
- 了解交互式仪表盘的概念
先建立一张地图
Section titled “先建立一张地图”Plotly 最适合按“什么时候要让用户自己探索图表”来理解:

所以这节真正想解决的是:
- 交互图到底在补静态图的哪一层能力
- 什么时候它是加分,什么时候反而会显得多余
为什么需要交互式图表?
Section titled “为什么需要交互式图表?”| 对比 | 静态图(Matplotlib/Seaborn) | 交互图(Plotly) |
|---|---|---|
| 鼠标悬停 | 不支持 | 显示详细数据 |
| 缩放拖动 | 不支持 | 自由缩放和平移 |
| 数据筛选 | 不支持 | 可点击图例隐藏/显示 |
| 导出 | 保存为图片 | 图片 + HTML 网页 |
| 使用场景 | 论文、报告 | 数据探索、网页展示 |
flowchart LR A["我的图表需要<br/>交互吗?"] --> B{"使用场景"} B -->|"论文/报告/PPT"| C["Matplotlib / Seaborn<br/>静态图足够"] B -->|"数据探索/演示"| D["Plotly<br/>交互更方便"] B -->|"网站/仪表盘"| E["Plotly + Dash<br/>交互式应用"]
style C fill:#e3f2fd,stroke:#1565c0,color:#333 style D fill:#e8f5e9,stroke:#2e7d32,color:#333 style E fill:#fff3e0,stroke:#e65100,color:#333一个更适合新人的总类比
Section titled “一个更适合新人的总类比”你可以把 Plotly 理解成:
- 一张可以拿在手里自己翻看、放大和筛选的图
静态图更像:
- 已经印好的海报
交互图更像:
- 带放大镜和筛选按钮的电子地图
所以它最适合:
- 读者自己继续探索
而不是所有场景都强行加交互。
# 安装# python -m pip install --upgrade plotly
# Plotly Express:快速绑图(推荐)import plotly.express as px
# Plotly Graph Objects:更底层的控制import plotly.graph_objects as go
import pandas as pdimport numpy as npPlotly Express 快速入门
Section titled “Plotly Express 快速入门”Plotly Express 是 Plotly 的高级接口,一行代码就能创建漂亮的交互式图表。
第一次学 Plotly 时,最稳的顺序
Section titled “第一次学 Plotly 时,最稳的顺序”更稳的顺序通常是:
- 先用
px.scatter()、px.line()、px.bar()熟悉基本交互 - 再看热力图、3D 和动画图
- 最后再看仪表盘和网页展示
这样会比一开始就扑到 Dash 上更不容易乱。
# 使用内置数据集df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", # 按物种分颜色 size="petal_length", # 用花瓣长度控制点大小 hover_data=["petal_width"], # 悬停显示花瓣宽度 title="鸢尾花数据集 - 交互式散点图")fig.show()运行后,你会看到一个可以悬停、缩放、拖动的图表!
df = px.data.gapminder()# 筛选中国、美国、日本的数据countries = df[df["country"].isin(["China", "United States", "Japan"])]
fig = px.line(countries, x="year", y="gdpPercap", color="country", title="中美日人均 GDP 变化", labels={"gdpPercap": "人均 GDP(美元)", "year": "年份", "country": "国家"})fig.show()df = px.data.tips()
fig = px.bar(df, x="day", y="total_bill", color="sex", barmode="group", # "group" 分组, "stack" 堆叠 title="各日消费(按性别分组)", labels={"total_bill": "消费金额", "day": "星期", "sex": "性别"})fig.show()df = px.data.tips()
fig = px.histogram(df, x="total_bill", color="time", nbins=20, marginal="box", # 边际图:"box", "violin", "rug" title="消费金额分布(带边际箱线图)")fig.show()df = px.data.tips()
fig = px.box(df, x="day", y="total_bill", color="smoker", notched=True, # 带缺口的箱线图 title="各日消费分布(按是否吸烟)")fig.show()饼图 / 甜甜圈图
Section titled “饼图 / 甜甜圈图”# 饼图fig = px.pie(df, names="day", values="total_bill", title="各日消费占比", hole=0.3) # hole > 0 变成甜甜圈图fig.show()# 计算相关系数df = px.data.iris()numeric_cols = df.select_dtypes(include="number")corr = numeric_cols.corr()
fig = px.imshow(corr, text_auto=".2f", color_continuous_scale="RdBu_r", title="鸢尾花特征相关性热力图")fig.show()3D 散点图
Section titled “3D 散点图”df = px.data.iris()
fig = px.scatter_3d(df, x="sepal_length", y="sepal_width", z="petal_length", color="species", title="鸢尾花 3D 散点图(可旋转!)")fig.show()你可以用鼠标拖动旋转这个 3D 图,从不同角度观察数据。
df = px.data.gapminder()
fig = px.scatter(df, x="gdpPercap", y="lifeExp", size="pop", color="continent", hover_name="country", animation_frame="year", # 按年份播放动画 animation_group="country", log_x=True, range_x=[100, 100000], range_y=[25, 90], title="各国发展轨迹(1952-2007)")fig.show()点击播放按钮,可以看到各国在不同年份的变化。这就是著名的 Hans Rosling 气泡图。
fig = px.scatter(px.data.iris(), x="sepal_width", y="sepal_length", color="species")
fig.update_layout( title=dict(text="自定义标题", font=dict(size=20)), xaxis_title="萼片宽度 (cm)", yaxis_title="萼片长度 (cm)", template="plotly_white", # 模板主题 width=800, height=500, legend_title="品种")
fig.show()| 模板名 | 风格 |
|---|---|
"plotly" | 默认蓝色背景 |
"plotly_white" | 白底(推荐) |
"plotly_dark" | 深色背景 |
"ggplot2" | R ggplot 风格 |
"simple_white" | 极简白底 |
一个很适合初学者先记的判断表
Section titled “一个很适合初学者先记的判断表”| 你的目标 | 更稳的第一反应 |
|---|---|
| 给论文或报告出图 | 静态图优先 |
| 自己探索数据细节 | Plotly 很合适 |
| 给别人做网页演示 | Plotly 很合适 |
| 只是想“更炫” | 先停一下,想清楚有没有必要 |
这个表特别适合新人,因为它会把“交互图很酷”重新拉回成一个使用场景判断。
# 保存为交互式 HTMLfig.write_html("my_chart.html")
# 保存为静态图片(需安装 kaleido)# python -m pip install --upgrade kaleidofig.write_image("my_chart.png", scale=2)fig.write_image("my_chart.svg")Plotly vs Matplotlib vs Seaborn
Section titled “Plotly vs Matplotlib vs Seaborn”| 特性 | Matplotlib | Seaborn | Plotly |
|---|---|---|---|
| 交互性 | 无 | 无 | 强 |
| 美观度 | 一般 | 好 | 好 |
| 学习难度 | 中 | 低 | 低 |
| 定制能力 | 极强 | 中 | 强 |
| 输出格式 | 图片/PDF | 图片/PDF | HTML/图片 |
| 适合场景 | 论文/精细控制 | 快速统计图 | 数据探索/展示 |
交互式仪表盘简介
Section titled “交互式仪表盘简介”在实际工作中,你可能需要将多个交互式图表组合成一个仪表盘(Dashboard)。
常用工具:
| 工具 | 特点 |
|---|---|
| Plotly Dash | Python 代码构建,功能强大 |
| Streamlit | 最简单,几行代码就能做应用 |
| Gradio | AI 模型演示专用 |
| Panel | Jupyter 生态集成好 |
一个简单的 Dash 示例(了解即可):
# python -m pip install --upgrade dashfrom dash import Dash, html, dccimport plotly.express as px
app = Dash(__name__)
df = px.data.gapminder().query("year == 2007")fig = px.scatter(df, x="gdpPercap", y="lifeExp", size="pop", color="continent", hover_name="country", log_x=True)
app.layout = html.Div([ html.H1("世界发展指标仪表盘"), dcc.Graph(figure=fig)])
# 运行:python app.py,然后打开 http://127.0.0.1:8050# app.run(debug=True)学完这一页,至少保留这张证据卡:
- 问题
- 这张图表回答的是比较、分布、趋势,还是关系
- 图表选择
- 折线图、柱状图、散点图、直方图、箱线图、热力图或交互式仪表板
- 工件
- 保存的图表图片/html 以及所用的数据切片
- 失败检查
- 尺度误导、图表过载、聚合错误或缺少标签
- 期望产出
- 带有一句说明洞察的图表成果
| Plotly Express 函数 | 图表类型 |
|---|---|
px.scatter() | 散点图 |
px.line() | 折线图 |
px.bar() | 柱状图 |
px.histogram() | 直方图 |
px.box() | 箱线图 |
px.pie() | 饼图 |
px.imshow() | 热力图 |
px.scatter_3d() | 3D 散点图 |
Plotly 的核心优势就是交互——鼠标悬停查看数据、缩放细看局部、动画展示变化。在数据探索和结果展示时非常好用。
这节最该带走什么
Section titled “这节最该带走什么”Plotly的核心价值不是炫,而是让读者能继续探索数据- 交互图最适合数据探索、网页展示和演示场景
- 第一次学时先掌握
px.scatter / px.line / px.bar这几类就够用了
练习 1:交互式探索
Section titled “练习 1:交互式探索”# 加载 gapminder 数据集# 1. 用 px.scatter 画出 2007 年各国 gdpPercap vs lifeExp 的关系# - 用 pop 控制点大小,continent 控制颜色# - 悬停显示 country# 2. 用 px.line 画出中国 1952-2007 年的 lifeExp 变化练习 2:数据分布
Section titled “练习 2:数据分布”# 加载 tips 数据集# 1. 用 px.histogram 画消费金额分布,用 marginal="violin" 添加边际图# 2. 用 px.box 按星期比较消费金额练习 3:动画图
Section titled “练习 3:动画图”# 用 gapminder 数据集制作动画散点图# 展示 1952-2007 年各国 gdpPercap vs lifeExp 的变化# 用 animation_frame="year"参考实现与讲解
- Gapminder 风格散点图要有意识地映射 x、y、size、color 和 hover text。hover 字段应帮助回答问题,而不是把所有列都塞进去。
- 国家或产品趋势线要先按时间排序,并确认 x 轴是日期或有序年份字段。未排序的时间数据会画出误导性的折线。
- 动态图必须服务于稳定的问题。如果动画反而妨碍比较,就补一张静态摘要图或最终帧说明。