Plotly深入浅出:Python新一代数据可视化完全指南
前言
作为Python的新一代数据可视化库,Plotly相比Matplotlib有两大优势:
- 简洁易用:图表对象像嵌套dict,通过修改属性改变形态,学习成本远低于Matplotlib
- 动态交互:图表可交互——点击查看数据、拖拽放大、隐藏数据列,也可导出为静态图
两种接口
| 接口 | 简称 | 特点 | 适用场景 |
|---|---|---|---|
plotly.graph_objects |
go | 面向对象,精细控制 | 定制化图表 |
plotly.express |
px | 函数式,快速绘图 | 探索性分析 |
核心思想:Figure = data(数据) + layout(布局)
# Figure就像一个嵌套的Python dict
fig = go.Figure(
data=[go.Scatter(x=[1,2,3], y=[4,5,6])],
layout=go.Layout(title="My Chart")
)
Part 1:plotly.graph_objects 绘图原理
Figure结构
import plotly.graph_objects as go
# 创建Figure
fig = go.Figure()
# 添加trace(数据层)
fig.add_trace(go.Scatter(
x=[1, 2, 3, 4],
y=[10, 11, 12, 13],
mode='lines+markers',
name='数据系列1'
))
# 修改layout(布局层)
fig.update_layout(
title='简单折线图',
xaxis_title='X轴',
yaxis_title='Y轴',
template='plotly_white'
)
fig.show()
常用Trace类型
| 类型 | 用途 | 示例 |
|---|---|---|
go.Scatter |
折线图/散点图 | 趋势分析 |
go.Bar |
柱形图 | 分类对比 |
go.Histogram |
直方图 | 分布分析 |
go.Heatmap |
热力图 | 相关性矩阵 |
go.Pie |
饼图 | 占比分析 |
go.Box |
箱线图 | 离群值检测 |
go.Surface |
3D曲面 | 三维数据 |
多子图
from plotly.subplots import make_subplots
# 创建2x2子图布局
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('图1', '图2', '图3', '图4')
)
# 添加trace到指定位置
fig.add_trace(go.Scatter(x=[1,2,3], y=[4,5,6]), row=1, col=1)
fig.add_trace(go.Bar(x=['A','B','C'], y=[10,20,30]), row=1, col=2)
fig.add_trace(go.Histogram(x=np.random.randn(1000)), row=2, col=1)
fig.add_trace(go.Pie(labels=['A','B','C'], values=[30,40,30]), row=2, col=2)
fig.update_layout(height=600, showlegend=False)
fig.show()
Part 2:plotly.express 快速绘图
基本用法
import plotly.express as px
import pandas as pd
# 准备数据
df = pd.DataFrame({
'城市': ['北京', '上海', '广州', '深圳'],
'GDP': [36000, 38000, 25000, 27000],
'人口': [2154, 2487, 1868, 1756]
})
# 一行代码绘图
fig = px.bar(df, x='城市', y='GDP', title='城市GDP对比')
fig.show()
内置数据集
# Plotly内置数据集
df = px.data.gapminder() # Gapminder世界发展数据
df = px.data.iris() # 鸢尾花数据集
df = px.data.tips() # 餐厅小费数据
df = px.data.stocks() # 股票数据
Part 3:5种图表实战对比
1. 柱形图
# go方式
fig = go.Figure()
fig.add_trace(go.Bar(
x=['产品A', '产品B', '产品C'],
y=[100, 150, 120],
name='销量',
marker_color='indianred'
))
fig.update_layout(title='产品销量对比')
# px方式(更简洁)
fig = px.bar(df, x='产品', y='销量', color='类别',
barmode='group', title='产品销量对比')
2. 折线图
# 股票数据示例
df = px.data.stocks()
# go方式
fig = go.Figure()
for col in ['GOOG', 'AAPL', 'AMZN']:
fig.add_trace(go.Scatter(
x=df['date'], y=df[col],
mode='lines',
name=col
))
fig.update_layout(title='科技股走势')
# px方式
fig = px.line(df, x='date', y=['GOOG', 'AAPL', 'AMZN'],
title='科技股走势')
3. 散点图
# 鸢尾花数据集
df = px.data.iris()
# go方式
fig = go.Figure()
for species in df['species'].unique():
subset = df[df['species'] == species]
fig.add_trace(go.Scatter(
x=subset['sepal_width'],
y=subset['sepal_length'],
mode='markers',
name=species
))
# px方式(自动分组+颜色映射)
fig = px.scatter(df, x='sepal_width', y='sepal_length',
color='species', size='petal_length',
title='鸢尾花数据分布')
4. 热力图
import numpy as np
# 相关性矩阵
corr = df[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']].corr()
# go方式
fig = go.Figure(data=go.Heatmap(
z=corr.values,
x=corr.columns,
y=corr.columns,
colorscale='RdBu_r',
zmin=-1, zmax=1
))
fig.update_layout(title='特征相关性热力图')
# px方式
fig = px.imshow(corr, text_auto='.2f',
color_continuous_scale='RdBu_r',
title='特征相关性热力图')
5. 直方图
# 生成正态分布数据
data = np.random.randn(1000)
# go方式
fig = go.Figure()
fig.add_trace(go.Histogram(
x=data,
nbinsx=30,
name='正态分布',
opacity=0.75
))
fig.update_layout(title='数据分布直方图')
# px方式
fig = px.histogram(x=data, nbins=30,
title='数据分布直方图',
labels={'x': '值', 'y': '频次'})
Part 4:样式与主题
内置主题
# 可用主题
themes = [
'plotly', # 默认主题
'plotly_white', # 白色背景
'plotly_dark', # 暗色主题
'ggplot2', # 仿ggplot2
'seaborn', # 仿seaborn
'simple_white', # 简洁白色
'presentation', # 演示用
]
fig.update_layout(template='plotly_dark')
自定义样式
fig.update_layout(
# 标题
title=dict(
text='图表标题',
font=dict(size=20, color='black'),
x=0.5 # 居中
),
# 坐标轴
xaxis=dict(
title='X轴标题',
showgrid=True,
gridwidth=1,
gridcolor='lightgray'
),
yaxis=dict(title='Y轴标题'),
# 图例
legend=dict(
orientation='h', # 水平排列
yanchor='bottom',
y=1.02,
xanchor='right',
x=1
),
# 尺寸
width=800,
height=500,
# 边距
margin=dict(l=50, r=50, t=80, b=50)
)
Part 5:导出与嵌入
导出静态图
# 需要安装kaleido: pip install kaleido
fig.write_image('chart.png') # PNG
fig.write_image('chart.svg') # SVG
fig.write_image('chart.pdf') # PDF
fig.write_html('chart.html') # 交互式HTML
嵌入Web应用
# Streamlit
import streamlit as st
st.plotly_chart(fig, use_container_width=True)
# Dash
from dash import Dash, dcc
app = Dash()
app.layout = dcc.Graph(figure=fig)
# Jupyter Notebook
fig.show() # 直接显示
实战案例:股票K线图
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# 创建带成交量的K线图
fig = make_subplots(
rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.03,
row_heights=[0.7, 0.3]
)
# K线
fig.add_trace(go.Candlestick(
x=df['date'],
open=df['open'],
high=df['high'],
low=df['low'],
close=df['close'],
name='K线'
), row=1, col=1)
# 成交量
fig.add_trace(go.Bar(
x=df['date'],
y=df['volume'],
name='成交量',
marker_color='rgba(0,0,255,0.3)'
), row=2, col=1)
fig.update_layout(
title='股票K线图',
xaxis_rangeslider_visible=False,
template='plotly_white',
height=600
)
fig.show()
go vs px 选择指南
| 场景 | 推荐 | 原因 |
|---|---|---|
| 探索性数据分析 | px | 一行代码,快速迭代 |
| 定制化报告 | go | 精细控制每个元素 |
| 多子图布局 | go + make_subplots | 灵活布局 |
| 动画/滑块 | px | 内置动画支持 |
| 3D图表 | go | 更多3D类型 |
| 发布级图表 | go | 完全控制样式 |
总结
Plotly的两种接口互补:
- px:快速原型,适合数据探索阶段
- go:精细控制,适合最终呈现阶段
两者可以混用——用px快速验证,再用go精调样式。
# px创建 → go修改
fig = px.scatter(df, x='x', y='y', color='group')
fig.update_traces(marker=dict(size=10, opacity=0.7))
fig.update_layout(template='plotly_dark')
Notebook文件:
F:\202507\plotly深入浅出.ipynb,5060+行完整教程,包含所有图表的代码和输出。
Stay tuned! 🚀