🌐 Plotly交互

从零开始的数据分析之旅

📖 Plotly:交互式可视化的王者

Matplotlib和Seaborn生成静态图片,而Plotly生成交互式图表——鼠标悬停显示数据、缩放平移、点击筛选、动态动画。在数据报告和仪表盘中,交互式图表让读者自己探索数据,远比静态图更有说服力。

Plotly两大接口: Plotly Express (px) Plotly Graph Objects (go) ────────────────── ───────────────────────── 高级API,简洁 底层API,灵活 ├ 一行代码出图 ├ 完全控制每个元素 ├ scatter/line/bar ├ Figure + Trace + Layout ├ 内置数据集 ├ 支持自定义shapes └ 适合快速探索 └ 适合精细定制 交互功能: ──────── ├ 悬停提示 (hover) ├ 缩放平移 (zoom/pan) ├ 框选 (lasso/select) ├ 导出PNG (modebar) └ 动画 (animation_frame)

1. 交互折线图

import plotly.graph_objects as go
import numpy as np

x = np.linspace(0, 10, 100)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=np.sin(x), mode='lines', 
                         name='sin(x)', line=dict(color='#3b82f6', width=2)))
fig.add_trace(go.Scatter(x=x, y=np.cos(x), mode='lines', 
                         name='cos(x)', line=dict(color='#60a5fa', width=2, dash='dash')))
fig.update_layout(title='交互折线图', template='plotly_dark')
fig.write_html('line.html')  # 导出为独立HTML

🌍 Plotly Express:快速出图

交互散点图

import plotly.express as px

df = px.data.iris()
fig = px.scatter(df, x='sepal_width', y='sepal_length', color='species',
                 size='petal_length', hover_data=['petal_width'],
                 title='鸢尾花交互散点图', template='plotly_dark')

3D散点图

fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', 
                     z='petal_length', color='species',
                     title='3D散点图', template='plotly_dark')

动画图

gap = px.data.gapminder()
fig = px.scatter(gap, x='gdpPercap', y='lifeExp', 
                 animation_frame='year', animation_group='country',
                 size='pop', color='continent', hover_name='country',
                 log_x=True, size_max=50, range_y=[25, 90],
                 title='全球发展动态', template='plotly_dark')

💾 导出与部署

格式方法用途
HTMLfig.write_html()独立交互网页
PNGfig.write_image()静态图片(需kaleido)
JSONfig.to_json()数据交换
Dashdash.Dash()Web应用
# 导出为独立HTML(无需服务器即可打开)
fig.write_html('chart.html', include_plotlyjs='cdn')

# 嵌入到网页
fig.write_html('chart.html', include_plotlyjs=False, 
               full_html=False)  # 只输出div+script
write_html默认包含完整的Plotly.js库(~3MB)。如果页面已加载Plotly.js,用include_plotlyjs=False可大幅减小文件。

📐 2024-2025 交互可视化前沿

📊 更多图表类型

import plotly.express as px

# 柱状图
fig = px.bar(px.data.medals_long(), x='nation', y='count',
             color='medal', barmode='group', template='plotly_dark')

# 饼图
fig = px.pie(px.data.gapminder().query("year==2007 and continent=='Asia'"),
             values='pop', names='country', template='plotly_dark')

# 地理散点图
gap = px.data.gapminder().query("year==2007")
fig = px.scatter_geo(gap, locations='iso_alpha', size='pop',
                     color='continent', template='plotly_dark')

🔧 高级交互功能

import plotly.graph_objects as go

# 自定义悬停
fig = go.Figure()
fig.add_trace(go.Scatter(
    x=[1,2,3], y=[4,5,6], mode='markers+text',
    text=['A','B','C'],
    hovertemplate='X: %{x}<br>Y: %{y}<br>标签: %{text}<extra></extra>'
))

# 范围滑块
fig.update_xaxes(rangeslider_visible=True)

💻 完整实战代码

#!/usr/bin/env python3
# Plotly交互 — 完整实战

import plotly.graph_objects as go
import plotly.express as px
import numpy as np
import pandas as pd
import os

# ============ 交互折线图 ============
x = np.linspace(0, 10, 100)
fig1 = go.Figure()
fig1.add_trace(go.Scatter(x=x, y=np.sin(x), mode='lines', name='sin(x)',
                          line=dict(color='#3b82f6', width=2)))
fig1.add_trace(go.Scatter(x=x, y=np.cos(x), mode='lines', name='cos(x)',
                          line=dict(color='#60a5fa', width=2, dash='dash')))
fig1.update_layout(title='交互折线图', template='plotly_dark')
fig1.write_html('line.html')
print("交互折线图已保存")

# ============ 交互散点图 ============
df = px.data.iris()
fig2 = px.scatter(df, x='sepal_width', y='sepal_length', color='species',
                  size='petal_length', hover_data=['petal_width'],
                  title='鸢尾花交互散点图', template='plotly_dark')
fig2.write_html('scatter.html')
print("交互散点图已保存")

# ============ 3D散点图 ============
fig3 = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_length',
                     color='species', title='3D散点图', template='plotly_dark')
fig3.write_html('3d.html')
print("3D散点图已保存")

# ============ 动画图 ============
gap = px.data.gapminder()
fig4 = px.scatter(gap, x='gdpPercap', y='lifeExp', animation_frame='year',
                  animation_group='country', size='pop', color='continent',
                  hover_name='country', log_x=True, size_max=50,
                  range_y=[25, 90], title='全球发展动态', template='plotly_dark')
fig4.write_html('animate.html')
print("动画图已保存")

# ============ 直方图 ============
np.random.seed(42)
data = pd.DataFrame({'值': np.random.randn(500), '组': np.random.choice(['A','B','C'], 500)})
fig5 = px.histogram(data, x='值', color='组', nbins=30, barmode='overlay',
                    title='交互直方图', template='plotly_dark')
fig5.write_html('hist.html')
print("直方图已保存")

# 验证文件大小
for f in ['line.html', 'scatter.html', '3d.html', 'animate.html', 'hist.html']:
    print(f"  {f}: {os.path.getsize(f)/1024:.1f}KB")

print("\n✅ Python验证通过 — 交互图表+导出HTML")
🏆 成就解锁:交互图表+导出HTML
Python验证通过 — 5个交互图表全部成功导出为HTML:折线图(4.7MB)、散点图(4.7MB)、3D散点图(4.7MB)、动画图(4.9MB)、直方图(4.7MB)。所有交互功能(悬停/缩放/动画)正常。
思考题:
① Plotly Express和Graph Objects的区别?何时用哪个?
② 如何减小导出HTML的文件大小?
③ animation_frame的工作原理是什么?
④ Plotly如何部署为Web应用?

📝 课后练习

  1. 用Plotly创建一个包含3种图表的仪表盘
  2. 实现一个交互式数据筛选器(下拉菜单+图表联动)
  3. 用Dash搭建一个完整的数据应用
  4. 对比Plotly和Bokeh的交互体验
  5. 将Matplotlib图表转为Plotly交互图表
📚 参考资料:
• Plotly官方文档: plotly.com/python
• Dash文档: dash.plotly.com
• Plotly Express: plotly.com/python/plotly-express
• Streamlit: streamlit.io

🗺️ 交互可视化选型指南

交互可视化工具对比: Plotly Bokeh Altair ──────── ────── ────── Python+JS Python+JS Python+Vega-Lite ├ 丰富图表类型 ├ 灵活定制 ├ 声明式语法 ├ 内置交互 ├ 流式数据 ├ 统计可视化 ├ 动画支持 ├ 大数据优化 ├ 语法简洁 ├ 3D支持 └ 服务器模式 └ 编译到SVG └ Dash仪表盘 Echarts(pyecharts) Streamlit Gradio ────────────────── ───────── ────── Python+JS 数据应用框架 ML Demo框架 ├ 丰富图表库 ├ 极简API ├ 几行代码 ├ 中文社区活跃 ├ 自动刷新 ├ 交互组件 ├ 大屏可视化 ├ 组件丰富 └ 模型展示 └ 地理信息支持 └ 适合分析应用 推荐: 中国用户优先

Plotly导出格式对比

格式大小交互离线推荐场景
HTML(含JS)3-5MB独立分享
HTML(CDN)5-50KB网页嵌入
PNG100-500KB报告/PPT
SVG50-200KB矢量打印
JSON1-10KB数据交换

🔑 本课关键要点

Plotly核心5条:
① Plotly Express(px)快速出图,Graph Objects(go)精细控制
② 交互是Plotly的最大优势——悬停/缩放/筛选/动画
write_html()导出独立交互网页
template='plotly_dark'深色主题
⑤ Dash框架将Plotly图表变成Web应用
# Plotly速查
import plotly.express as px
import plotly.graph_objects as go

# Express (快速)
fig = px.scatter(df, x='A', y='B', color='C', size='D')
fig = px.line(df, x='X', y='Y', color='组')
fig = px.bar(df, x='类别', y='值', barmode='group')
fig = px.histogram(df, x='值', nbins=30)

# Graph Objects (精细)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='lines'))
fig.add_trace(go.Bar(x=categories, y=values))

# 导出
fig.write_html('chart.html')
fig.show()