跳到主要内容

Plotly 交互可视化

问题

Plotly 适合什么场景?如何创建交互式图表和数据看板?

答案

Plotly 定位

维度Matplotlib/SeabornPlotly
输出静态图片交互 HTML
操作悬停、缩放、筛选
看板不支持Dash 框架
API命令式声明式
适用论文、脚本报告、Web、看板

Plotly Express(快速出图)

Plotly Express 常用图表
import plotly.express as px
import pandas as pd

# 内置数据集
df = px.data.gapminder()
df_2007 = df[df['year'] == 2007]

# 1. 散点图(悬停显示国家信息)
fig = px.scatter(
df_2007,
x='gdpPercap', y='lifeExp',
size='pop', color='continent',
hover_name='country',
log_x=True,
title='2007 年全球 GDP vs 预期寿命'
)
fig.show()

# 2. 柱状图
top10 = df_2007.nlargest(10, 'pop')
fig = px.bar(
top10, x='country', y='pop',
color='continent',
title='2007 年人口 Top 10'
)
fig.show()

# 3. 折线图(多国 GDP 趋势)
countries = ['China', 'United States', 'Japan', 'Germany']
fig = px.line(
df[df['country'].isin(countries)],
x='year', y='gdpPercap',
color='country',
title='人均 GDP 趋势'
)
fig.show()

高级图表

特殊图表类型
import plotly.express as px
import plotly.graph_objects as go

# 1. 漏斗图
fig = px.funnel(
pd.DataFrame({
'stage': ['访问', '注册', '下单', '付款', '复购'],
'count': [10000, 3000, 1500, 1200, 400]
}),
x='count', y='stage',
title='用户转化漏斗'
)
fig.show()

# 2. 桑基图(流转路径)
fig = go.Figure(go.Sankey(
node=dict(label=['首页', '列表页', '详情页', '购物车', '支付', '流失']),
link=dict(
source=[0, 0, 1, 1, 2, 2, 3, 3],
target=[1, 5, 2, 5, 3, 5, 4, 5],
value= [600, 400, 400, 200, 300, 100, 250, 50]
)
))
fig.update_layout(title='用户行为路径')
fig.show()

# 3. 热力图
import numpy as np
fig = px.imshow(
np.random.rand(7, 24),
labels=dict(x='小时', y='星期', color='活跃度'),
x=[f'{h}:00' for h in range(24)],
y=['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
color_continuous_scale='YlOrRd',
title='用户活跃热力图'
)
fig.show()

动画图表

时间轴动画
import plotly.express as px

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()

Graph Objects(精细控制)

组合多类型图表
import plotly.graph_objects as go

months = ['1月', '2月', '3月', '4月', '5月', '6月']
revenue = [120, 135, 140, 155, 170, 180]
cost = [80, 85, 90, 95, 100, 105]
profit_rate = [33, 37, 36, 39, 41, 42]

fig = go.Figure()

# 柱状图:收入和成本
fig.add_trace(go.Bar(x=months, y=revenue, name='收入', marker_color='#2196F3'))
fig.add_trace(go.Bar(x=months, y=cost, name='成本', marker_color='#FF9800'))

# 折线图:利润率(次 Y 轴)
fig.add_trace(go.Scatter(
x=months, y=profit_rate,
name='利润率%', yaxis='y2',
mode='lines+markers',
line=dict(color='#4CAF50', width=3)
))

fig.update_layout(
title='月度财务概览',
yaxis=dict(title='金额(万元)'),
yaxis2=dict(title='利润率(%)', overlaying='y', side='right'),
barmode='group'
)
fig.show()

Dash 看板(简介)

Dash 简易看板结构
# pip install dash
from dash import Dash, html, dcc
import plotly.express as px

app = Dash(__name__)

df = px.data.gapminder()

app.layout = html.Div([
html.H1('全球数据看板'),
dcc.Dropdown(
id='continent-dropdown',
options=[{'label': c, 'value': c} for c in df['continent'].unique()],
value='Asia'
),
dcc.Graph(id='scatter-plot'),
dcc.Graph(id='line-plot')
])

# 回调函数根据筛选更新图表(略)
# @app.callback(Output('scatter-plot', 'figure'), Input('continent-dropdown', 'value'))

if __name__ == '__main__':
app.run(debug=True)

常见面试问题

Q1: Plotly 和 Matplotlib 怎么选?

答案

  • Matplotlib/Seaborn:论文、报告中需要静态高质量图
  • Plotly:需要交互(悬停、缩放、筛选)的场景
  • Plotly + Dash:需要搭建 Web 看板
  • 实际工作中两者经常搭配使用

Q2: 如何导出 Plotly 图表?

答案

# 交互 HTML(推荐)
fig.write_html('chart.html')

# 静态图片(需安装 kaleido)
fig.write_image('chart.png', scale=2)
fig.write_image('chart.svg')
fig.write_image('chart.pdf')

Q3: Plotly Express 和 Graph Objects 什么区别?

答案

  • Plotly Express (px):高级接口,一行代码出图,接受 DataFrame
  • Graph Objects (go):底层接口,精细控制每个元素
  • 通常先用 px 快速出图,需要深度定制时切换到 go

相关链接