关于 plotly
Plotly 是用于交互式数据可视化的 Python 工具,面向分析人员和开发者。它提供简洁的 Plotly Express API,也支持通过 Graph Objects 精细控制图表。
主要功能
- 01交互式统计图表
- 023D 与地理可视化
- 03动画与时间序列图
- 04图表导出为 HTML
- 05Graph Objects 精细定制
适用场景
- 01在 Notebook 中探索数据
- 02制作交互式网页图表
- 03构建 Dash 仪表板
- 04生成可分享的 HTML 报告
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tondevrel/ scientific-agent-skills --skill plotly安装后在 Claude Code 中输入/plotly确认已加载。
详细介绍
Plotly - 交互式可视化
Plotly 提供种类丰富的交互式图表。其「Plotly Express」API 专为整洁的 DataFrame 设计,速度快且易于使用;而「Graph Objects」则可对每条轨迹和每个属性进行底层控制。
适用场景
- 为 Web 应用或 Jupyter 笔记本创建交互式图表
- 可视化 3D 数据(曲面、散点、网格)
- 地理地图(地图散点图、分级统计地图),并与 Mapbox 集成
- 金融图表(蜡烛图、OHLC)
- 探索需要缩放查看特定区域的大型数据集
- 创建动画(时间序列滑块)
- 构建可用于生产环境的仪表板(通过 Dash)
参考文档
官方文档:https://plotly.com/python/
Plotly Express:https://plotly.com/python/plotly-express/
搜索模式:px.scatter、go.Figure、fig.update_layout、fig.write_html、px.choropleth
核心原则
Plotly Express (px) 与 Graph Objects (go)
| 特性 | Plotly Express (px) | Graph Objects (go) |
|---|---|---|
| 复杂度 | 高级、简洁。 | 底层、冗长。 |
| 数据格式 | 整洁(长格式)DataFrame。 | 列表、数组、字典或 DataFrame。 |
| 自定义 | 良好(使用 update_*)。 | 最大程度 / 完全控制。 |
| 开发速度 | 非常快。 | 较慢。 |
适合使用 Plotly 的场景
- 交互式探索(悬停、缩放)
- 3D 和地理空间可视化
- 导出为独立的交互式 HTML 文件
- 与 Dash 集成
不适合使用 Plotly 的场景
- 需要达到出版质量的静态 LaTeX 图表(使用 Matplotlib)
- 生成超大型静态图像(Matplotlib 更快)
- 低内存环境(Plotly 基于 JSON 的图表占用大量内存)
快速参考
安装
pip install plotly pandas
标准导入
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
基本模式 - Plotly Express
import plotly.express as px
# Load data
df = px.data.iris()
# Create interactive scatter plot
fig = px.scatter(df, x="sepal_width", y="sepal_length",
color="species", size="petal_length",
hover_data=['petal_width'])
# Display
fig.show()
关键规则
✅ 应该做
- 优先使用 Plotly Express——90% 的任务用 px 会更简单
- 优先使用整洁数据——确保每个观测值占一行,以便轻松映射颜色和坐标轴
- 使用 update_layout——简洁地修改标题、字体和背景颜色
- 保存为 HTML——使用
fig.write_html("plot.html")分享交互式图表 - 善用悬停数据——为数据点补充上下文,同时避免图表杂乱
- 设置图表模板——使用
template="plotly_dark"或"ggplot2"即可快速应用样式 - 使用 marginal_x/y——在 px.scatter 中快速向边缘添加直方图或箱线图
❌ 不应该做
- 将超大型数据集传给浏览器——绘制超过 50k 个点可能导致界面卡顿;请使用 datashader 或抽稀
- 手动循环使用 go——如果 px 能实现,就不要用 for 循环在 go 中添加轨迹
- 忘记设置坐标轴标签——px 使用列名;在 DataFrame 中重命名列可获得更好的标签
- 过度使用动画——流畅的动画很酷,但过多的动态元素会分散对数据的注意力
反模式(绝对不要)
# ❌ BAD: Over-complicating a simple plot with Graph Objects
fig = go.Figure()
for species in df['species'].unique():
sub = df[df['species'] == species]
fig.add_trace(go.Scatter(x=sub['sepal_w'], y=sub['sepal_l'], name=species))
# ✅ GOOD: Use Plotly Express (One line, automatic legend/colors)
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species")
# ❌ BAD: Mixing list-style data with DataFrame-style data in px
px.scatter(x=[1,2,3], y=df['column']) # Can lead to alignment issues
# ✅ GOOD: Stick to the DataFrame
px.scatter(df, x="column_a", y="column_b")
深入了解 Plotly Express (px)
统计图表
# Boxplot with points
fig = px.box(df, x="day", y="total_bill", color="smoker", points="all")
# Violin plot with box inside
fig = px.violin(df, x="day", y="total_bill", color="sex", box=True, points="all")
# Heatmap (Density Contour)
fig = px.density_heatmap(df, x="total_bill", y="tip", marginal_x="histogram", marginal_y="histogram")
时间序列与分面
df = px.data.stocks()
# Multiple lines from wide data
fig = px.line(df, x='date', y=["GOOG", "AAPL", "AMZN"], title="Tech Stocks")
# Faceting (Subplots by category)
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", color="smoker",
facet_col="day", facet_row="time")
3D 可视化
散点图、折线图和曲面图
# 3D Scatter
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width', color='species')
# 3D Surface (Using Graph Objects)
z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')
fig = go.Figure(data=[go.Surface(z=z_data.values)])
fig.update_layout(title='Mt Bruno Elevation', autosize=False,
width=500, height=500, margin=dict(l=65, r=50, b=65, t=90))
地理空间分析
地图与分级统计地图
# Scatter on a map
df = px.data.gapminder().query("year == 2007")
fig = px.scatter_geo(df, locations="iso_alpha", color="continent",
hover_name="country", size="pop",
projection="natural earth")
# Detailed Mapbox Choropleth (Needs token or use open-street-map)
fig = px.choropleth_mapbox(df, geojson=counties, locations='fips', color='unemp',
color_continuous_scale="Viridis",
mapbox_style="carto-positron",
zoom=3, center = {"lat": 37.0902, "lon": -95.7129})
布局与样式(fig.update_*)
微调外观
fig = px.scatter(df, x="x", y="y")
# Global layout updates
fig.update_layout(
title="Custom Styled Plot",
xaxis_title="Dimension X",
yaxis_title="Dimension Y",
font=dict(family="Courier New, monospace", size=18, color="RebeccaPurple"),
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
plot_bgcolor="white"
)
# Axis specific updates
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='LightPink')
fig.update_yaxes(zeroline=True, zerolinewidth=2, zerolinecolor='Black')
高级交互:动画
df = px.data.gapminder()
fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year",
animation_group="country",
size="pop", color="continent", hover_name="country",
log_x=True, size_max=55, range_x=[100, 100000], range_y=[25, 90])
实用工作流
1. 导出交互式科学报告
def create_interactive_report(df, filename="report.html"):
"""Generates a multi-chart HTML report."""
fig1 = px.scatter(df, x="A", y="B", color="C")
fig2 = px.histogram(df, x="A", color="C")
with open(filename, 'a') as f:
f.write(fig1.to_html(full_html=False, include_plotlyjs='cdn'))
f.write(fig2.to_html(full_html=False, include_plotlyjs='cdn'))
# Useful for sharing findings with non-technical stakeholders
2. 金融仪表板片段(蜡烛图)
import pandas as pd
from datetime import datetime
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
fig = go.Figure(data=[go.Candlestick(x=df['Date'],
open=df['AAPL.Open'],
high=df['AAPL.High'],
low=df['AAPL.Low'],
close=df['AAPL.Close'])])
# Remove rangeslider for cleaner look
fig.update_layout(xaxis_rangeslider_visible=False)
3. 使用 go.Figure 混合子图
from plotly.subplots import make_subplots
fig = make_subplots(rows=1, cols=2, subplot_titles=("Plot A", "Plot B"))
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]), row=1, col=1)
fig.add_trace(go.Bar(x=[1, 2, 3], y=[2, 3, 5]), row=1, col=2)
fig.update_layout(height=600, width=800, title_text="Side-by-Side Comparison")
性能优化
大型数据集使用 WebGL
# For scatter plots with >10,000 points, use Scattergl (Graph Objects)
# or tell px to use webgl (available in newer versions)
fig = px.scatter(df, x="large_x", y="large_y", render_mode="webgl")
# WebGL drastically improves performance by using the GPU for rendering.
常见陷阱与解决方案
笔记本中的 JSON 开销
# ❌ Problem: Notebook file size explodes to 50MB
# ✅ Solution: Display as static image (requires kaleido) or use a different renderer
# fig.show(renderer="png") # Static
# OR: Clear output after viewing
动画中的坐标轴缩放
# ❌ Problem: Axes jump around during animation
# ✅ Solution: Manually fix the ranges
fig = px.scatter(df, x="x", y="y", animation_frame="time",
range_x=[0, 100], range_y=[0, 100])
处理图例中缺失的类别
# ❌ Problem: Colors change when filtering data because categories disappear
# ✅ Solution: Pass a category_orders dictionary
fig = px.scatter(df, x="x", y="y", color="category",
category_orders={"category": ["A", "B", "C", "D"]})
最佳实践
- 优先使用 Plotly Express - 90% 的任务都从
px开始;只有在需要精细控制时才使用go - 使用整洁的 DataFrame - 确保每条观测数据占一行,便于映射到视觉属性
- 使用
update_layout设置样式 - 轻松修改标题、字体和背景颜色,无需重新创建图表 - 保存为 HTML 以便分享 - 使用
fig.write_html("plot.html")与利益相关者分享交互式图表 - 利用悬停数据 - 为数据点补充上下文,同时避免图表杂乱
- 设置图表模板 - 使用
template="plotly_dark"或"ggplot2",快速应用专业样式 - 使用边际图 - 在
px.scatter中使用marginal_x和marginal_y,快速添加直方图或箱线图 - 优化大型数据集的呈现 - 对于超过 50k 个数据点的数据集,使用 WebGL 渲染或 datashader
- 固定动画中的坐标轴范围 - 使用
range_x和range_y,防止动画播放期间坐标轴跳动 - 设置类别顺序 - 使用
category_orders,在筛选数据时保持颜色一致
Plotly 弥合了静态分析与交互式探索之间的鸿沟,是将科学洞见从笔记本带到 Web 的最佳工具。
评论
支持 Markdown