python3可视化之plotly基本使用
Plotly是一个功能强大的Python交互式可视化库。Plotly的动态可视化功能主要基于 JavaScript 和 Web 浏览器的交互能力。通过Plotly创建图表时,Plotly会将图表数据和配置信息转换为 JSON 格式,并通过 Plotly.js 在浏览器中渲染图表。
安装 pip install plotly
保存为图片需安装 :pip install kaleido==0.1.*
核心特性:
交互性:支持缩放、平移、悬停查看数据详情等功能,用户可直接与图表互动。
双接口设计:Plotly Express (px):高级接口,语法简洁(类似 Seaborn),快速创建常见图表。Graph Objects (go):低级接口,提供精细化控制,适合定制复杂图表。
多样化图表:支持 40+ 图表类型,包括散点图、3D图、热力图、地图、箱线图等。
双接口设计:Plotly Express (px):高级接口,语法简洁(类似 Seaborn),快速创建常见图表。Graph Objects (go):低级接口,提供精细化控制,适合定制复杂图表。
多样化图表:支持 40+ 图表类型,包括散点图、3D图、热力图、地图、箱线图等。
常用配置
import plotly.graph_objects as go
import plotly.io as pio
x = [1, 2, 3, 4, 5]
y = [i + 60 for i in x]
c = [[i + 5, i - 5] for i in y]
fig = go.Figure(
data=[
go.Scatter(
x=x,
y=y,
mode="markers+lines",
customdata=c, # 传递额外数据
hovertemplate="<b>%{meta[1]}</b> 观测值<br>" # 鼠标悬停模板
+ "X轴: %{x}<br>"
+ "Y轴: %{y:.2f}<br>" # 数值格式化
+ "max: %{customdata[0]}%<br>"
+ "min: %{customdata[1]}%<br>"
+ "日期: %{meta[0]|%Y-%m-%d}<br>", # 日期格式化
)
]
)
fig.update_layout(
title={
"text": "标题",
"font": {"family": "Arial", "size": 24, "color": "black"},
"x": 0.90,
"xanchor": "right",
},
xaxis={
"title": "X轴标签",
"tickangle": 45,
"title_standoff": 25, # title_standoff调整标签与轴线之间的距离
"range": [0, 6], # 坐标轴范围
"autorange": False, # autorange关闭自动缩放
"dtick": 2, # 坐标轴刻度间隔
},
yaxis_range=[60, 66],
yaxis_dtick=1,
hoverlabel={
"bgcolor": "rgba(255,255,255,0.9)",
"font_size": 12,
}, # 悬停提示框的样式
)
fig.update_traces(
meta=[
["2025-04-13", "A"],
["2025-04-16", "B"],
["2025-04-16", "A"],
["2025-04-15", "B"],
["2025-04-17", "C"],
]
) # 元数据注入
config = {
"displaylogo": False, # 隐藏Plotly官方logo
"scrollZoom": True, # 开启鼠标滚轮缩放
}
fig.show(config=config) # 显示图表
pio.write_image(fig, "../../charts/figure.png") # 保存为PNG
pio.write_image(fig, "../../charts/figure_highres.png", scale=2) # 保存为高分辨率PNG,scale值越大分辨率越高
pio.write_image(fig, "../../charts/figure.jpg") # 保存为JPEG
pio.write_image(fig, "../../charts/figure.pdf") # 保存为PDF
显示
散点图
import plotly.express as px
import pandas as pd
import plotly.io as pio
import plotly.figure_factory as ff
tips = pd.read_csv("../../seaborn-data-master/tips.csv")
fig = px.scatter(tips, x="total_bill", y="tip", title="账单金额-小费", color="sex")
pio.write_image(fig, "../../charts/scatter-px.png")
# 多子图
fig = px.scatter(tips, x="total_bill", y="tip", facet_col="day", facet_row="time")
pio.write_image(fig, "../../charts/scatter-px-facet.png")
df = pd.read_csv("../../seaborn-data-master/car_crashes.csv")
# 气泡图
fig = px.scatter(df, x="speeding", y="alcohol", size="total", title="car crashes")
pio.write_image(fig, "../../charts/scatter-bubble-px.png")
# 散点矩阵图:展示多变量之间的相关性
fig = ff.create_scatterplotmatrix(
df,
diag="histogram",
width=1200,
height=1200,
)
pio.write_image(fig, "../../charts/scatter-matrix-px.png")
普通散点图
多子图
气泡图
散点矩阵图

graph_objects接口
import plotly.graph_objects as go
import pandas as pd
import plotly.io as pio
tips = pd.read_csv("../../seaborn-data-master/tips.csv")
df_m = tips.query("sex=='Male'")
df_f = tips.query("sex=='Female'")
traces = [
go.Scatter(x=df_m["total_bill"], y=df_m["tip"], mode="markers", name="Male"),
go.Scatter(x=df_f["total_bill"], y=df_f["tip"], mode="markers", name="Female"),
]
layout = go.Layout(
title="账单金额-小费",
xaxis_title="total_bill",
yaxis_title="tip",
)
fig = go.Figure(data=traces, layout=layout)
pio.write_image(fig, "../../charts/scatter-go.png")
折线图
import plotly.express as px
import pandas as pd
import plotly.io as pio
df = pd.read_csv("../../seaborn-data-master/healthexp.csv")
fig = px.line(df, x="Year", y="Life_Expectancy", color="Country")
fig.update_xaxes(title_text="国家") # 设置 X 轴标签
fig.update_yaxes(title_text="平均寿命") # 设置 Y 轴标签
fig.update_xaxes(tickangle=45, tickfont=dict(size=10)) # 调整 X 轴刻度角度和字体大小
fig.update_yaxes(dtick=5, tickfont=dict(size=10)) # 设置 Y 轴刻度间隔和字体大小
fig.update_yaxes(range=[65, 90]) # 设置 Y 轴范围
pio.write_image(fig, "../../charts/line-px.png")
graph_objects接口
import plotly.graph_objects as go
import pandas as pd
import plotly.io as pio
df = pd.read_csv("../../seaborn-data-master/healthexp.csv")
countries = df["Country"].unique()
data_country = [df.query(f"Country=='{c}'") for c in countries]
# 图例分组
traces = [go.Scatter(x=df_c["Year"], y=df_c["Spending_USD"], name=countries[i], legendgroup=countries[i]) for i, df_c in enumerate(data_country)]
traces = traces + [
go.Scatter(x=df_c["Year"], y=df_c["Life_Expectancy"], yaxis="y2", name=countries[i], legendgroup=countries[i], showlegend=False)
for i, df_c in enumerate(data_country)
]
layout = go.Layout(
title="双坐标轴折线图示例",
xaxis_title="年",
yaxis=dict(title="Spending_USD"),
yaxis2=dict(title="Life_Expectancy", overlaying="y", side="right"), # 使用overlaying属性将第二个Y轴叠加在第一个Y轴上,并设置在右侧
legend=dict(yanchor="middle", y=0.5, xanchor="left", x=1.1, title=dict(text="Country")), # 右侧垂直居中
)
fig = go.Figure(data=traces, layout=layout) # 创建图表对象
pio.write_image(fig, "../../charts/line-go.png")
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import plotly.io as pio
fig = make_subplots(specs=[[{"secondary_y": True}]])
df = pd.read_csv("../../seaborn-data-master/healthexp.csv")
countries = df["Country"].unique()
data_country = [df.query(f"Country=='{c}'") for c in countries]
for country, df_c in zip(countries, data_country):
fig.add_trace(
go.Scatter(
x=df_c["Year"],
y=df_c["Spending_USD"],
name=country,
legendgroup=country,
mode="lines+markers",
),
secondary_y=False,
)
fig.add_trace(
go.Scatter(
x=df_c["Year"],
y=df_c["Life_Expectancy"],
name=country,
legendgroup=country,
showlegend=False,
mode="lines+markers",
),
secondary_y=True,
)
fig.update_layout(
title="双坐标轴折线图示例",
legend_title_text="国家",
xaxis_title="年",
) # 更新布局
fig.update_yaxes(title_text="Spending_USD", secondary_y=False) # 设置坐标轴标签
fig.update_yaxes(title_text="Life_Expectancy", secondary_y=True)
pio.write_image(fig, "../../charts/line-go-1.png")
柱状图
import plotly.express as px
import pandas as pd
import plotly.io as pio
# 柱状图
df = pd.read_csv("../../seaborn-data-master/healthexp.csv")
df_y = df.groupby("Year", as_index=False)[["Life_Expectancy"]].mean()
fig = px.bar(df_y, x="Year", y="Life_Expectancy", title="柱状图")
fig.update_yaxes(range=[65, 85]) # 设置 Y 轴范围
pio.write_image(fig, "../../charts/bar-px.png")
# 水平柱状图
df_c = df.groupby("Country", as_index=False)[["Life_Expectancy"]].mean()
df_c = df_c.sort_values("Life_Expectancy", ascending=False)
fig = px.bar(df_c, x="Life_Expectancy", y="Country", title="水平柱状图", orientation="h")
fig.update_yaxes(autorange="reversed") # 反转 Y 轴顺序
fig.update_xaxes(range=[65, 85]) # 设置 Y 轴范围
fig.update_layout(margin=dict(l=50)) # 增加左侧边距
pio.write_image(fig, "../../charts/bar-h-px.png")
# 分组柱状图:barmode='group'
fig = px.bar(df[-18:], x="Year", y="Life_Expectancy", color="Country", barmode="group", title="分组柱状图", text="Life_Expectancy")
fig.update_yaxes(range=[65, 85]) # 设置 Y 轴范围
pio.write_image(fig, "../../charts/bar-group-px.png", scale=2)
柱状图
水平柱状图
分组柱状图
graph_objects接口
import plotly.graph_objects as go
import pandas as pd
import plotly.io as pio
# 分组柱状图
df = pd.read_csv("../../seaborn-data-master/healthexp.csv")
countries = df["Country"].unique()
df_country = [df.query(f"Country=='{c}'").tail(3) for c in countries]
traces = [
go.Bar(x=df_c["Year"], y=df_c["Life_Expectancy"], name=countries[i], text=df_c["Life_Expectancy"], textposition="auto")
for i, df_c in enumerate(df_country)
] # 创建分组柱状图并添加数据标签
layout = go.Layout(
barmode="group",
title="分组-平均寿命",
xaxis_title="年",
yaxis=dict(title="Life_Expectancy"),
legend_title_text="Country",
bargap=0.2, # 修改分组间距
bargroupgap=0.1, # 修改组内柱状间距
)
fig = go.Figure(data=traces, layout=layout) # 创建图表对象
pio.write_image(fig, "../../charts/bar-group-go.png", scale=2)
# 堆积柱状图
df = pd.read_csv("../../seaborn-data-master/tips.csv")
df = df.groupby(["day", "time"], as_index=False)[["tip"]].mean() # 统计
times = df["time"].unique()
df_times = [df.query(f"time=='{t}'").drop(["time"], axis=1) for t in times]
fig = go.Figure()
for t, df_t in zip(times, df_times):
fig.add_trace(go.Bar(x=df_t["day"], y=df_t["tip"], name=t, text=df_t["tip"]))
fig.update_layout(
barmode="stack",
title="堆积柱状图",
xaxis_title="time",
yaxis_title="tip",
)
pio.write_image(fig, "../../charts/bar-stack-go.png", scale=2)
# 百分比堆积柱状图
df_times_total = pd.DataFrame()
days = df["day"].unique()
total = {day: 0 for day in days}
for i, df_t in enumerate(df_times):
for row in df_t.itertuples(): # 行遍历dataframe
total[row.day] = total[row.day] + row.tip # 计算总数
df_times[i] = df_t.set_index("day")
df_times_total = pd.DataFrame(
{
"day": list(total.keys()),
"total": list(total.values()),
}
)
df_times_total = df_times_total.set_index("day")
for i, df_t in enumerate(df_times):
df_times[i]["percent"] = df_t["tip"] / df_times_total["total"] # 计算百分比
fig = go.Figure()
for t, df_t in zip(times, df_times):
fig.add_trace(go.Bar(x=df_t.index.tolist(), y=df_t["percent"], name=t, text=[f"{p*100:.1f}%" for p in df_t["percent"]], textposition="inside"))
fig.update_layout(
barmode="stack",
title="百分比堆积柱状图",
xaxis_title="time",
yaxis_title="tip-百分比",
yaxis=dict(tickformat=".0%"), # 设置y轴刻度格式为百分比
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
)
pio.write_image(fig, "../../charts/bar-stack-p-go.png", scale=2)
堆积柱状图
百分比堆积柱状图

饼图
import plotly.express as px
import pandas as pd
import plotly.io as pio
# 饼图
df = pd.read_csv("../../seaborn-data-master/tips.csv")
df_day = df.groupby("day", as_index=False)[["total_bill", "tip"]].mean()
fig = px.pie(df_day, names="day", values="total_bill", title="饼图", hole=0.2)
pio.write_image(fig, "../../charts/pie-px.png")
graph_objects接口
import plotly.graph_objects as go
import pandas as pd
import plotly.io as pio
# 饼图
df = pd.read_csv("../../seaborn-data-master/tips.csv")
df_day = df.groupby("day", as_index=False)[["total_bill", "tip"]].mean()
# pull:特定切片高亮
# text:标签
# marker:样式
traces = [
go.Pie(
labels=df_day["day"],
values=df_day["total_bill"],
text=df_day["day"],
textposition="outside",
hole=0.2,
pull=[0, 0.1, 0, 0],
marker=dict(line=dict(color="white", width=5)),
)
]
# paper_bgcolor:图表背景色配置
layout = go.Layout(title="饼图", paper_bgcolor="lightgray")
fig = go.Figure(data=traces, layout=layout)
pio.write_image(fig, "../../charts/pie-go.png")
箱型图
import plotly.express as px
import pandas as pd
import plotly.io as pio
df = pd.read_csv("../../seaborn-data-master/tips.csv")
# 箱型图
fig = px.box(df, x="day", y="total_bill")
pio.write_image(fig, "../../charts/box-px.png")
# 箱型图带全部数据点
fig = px.box(df, x="day", y="total_bill", points="all")
pio.write_image(fig, "../../charts/box-points-px.png")
# 分组箱型图
fig = px.box(df, x="day", y="total_bill", color="time", boxmode="group") # 分组显示,默认
pio.write_image(fig, "../../charts/box-group-px.png")
fig = px.box(df, x="day", y="total_bill", color="time", boxmode="overlay") # 重叠
pio.write_image(fig, "../../charts/box-group-overlay-px.png")
箱型图
箱型图带全部数据点

分组箱型图


直方图
import plotly.express as px
import pandas as pd
import plotly.io as pio
df = pd.read_csv("../../seaborn-data-master/tips.csv")
# 直方图
fig = px.histogram(df, x="tip")
pio.write_image(fig, "../../charts/hist-px.png")
# 分组直方图
fig = px.histogram(df, x="tip", color="time", histnorm="probability", barmode="group")
pio.write_image(fig, "../../charts/hist-group-px.png")
fig = px.histogram(df, x="tip", color="time", histnorm="probability", barmode="overlay")
fig.update_layout(bargap=0.2, bargroupgap=0.1)
pio.write_image(fig, "../../charts/hist-group-overlay-px.png")
分组直方图
子图布局
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import plotly.io as pio
df = pd.read_csv("../../seaborn-data-master/tips.csv")
df_thur = df.query('day=="Thur"')
df_fri = df.query('day=="Fri"')
# 多子图
fig = make_subplots(rows=2, cols=1, subplot_titles=("Thur", "Fri")) # 创建子图布局
fig.add_trace(go.Scatter(x=df_thur["total_bill"], y=df_thur["tip"], mode="markers", name="Thur"), row=1, col=1)
fig.add_trace(go.Scatter(x=df_fri["total_bill"], y=df_fri["tip"], mode="markers", name="Fri"), row=2, col=1)
fig.update_layout(height=600, width=600, title_text="tips")
pio.write_image(fig, "../../charts/subplot-go.png")
# 多子图共享坐标轴
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, subplot_titles=("Thur", "Fri")) # 创建子图布局
fig.add_trace(go.Scatter(x=df_thur["total_bill"], y=df_thur["tip"], mode="markers", name="Thur"), row=1, col=1)
fig.add_trace(go.Scatter(x=df_fri["total_bill"], y=df_fri["tip"], mode="markers", name="Fri"), row=2, col=1)
fig.update_layout(height=600, width=600, title_text="tips")
pio.write_image(fig, "../../charts/subplot-sx-go.png")
express接口
import plotly.express as px
from plotly.subplots import make_subplots
import pandas as pd
import plotly.io as pio
tips = pd.read_csv("../../seaborn-data-master/tips.csv")
fig = make_subplots(rows=2, cols=1, subplot_titles=("day", "time")) # 创建子图布局
fig1 = px.scatter(tips, x="total_bill", y="tip", color="day")
for i in range(len(fig1.data)):
fig.add_trace(fig1.data[i], row=1, col=1)
fig2 = px.scatter(tips, x="total_bill", y="tip", color="time")
for i in range(len(fig2.data)):
fig.add_trace(fig2.data[i], row=2, col=1)
fig.update_layout(height=600, width=600, title_text="tips") # 更新布局
pio.write_image(fig, "../../charts/subplot-px.png")
模板
import plotly.express as px
import pandas as pd
import plotly.io as pio
tips = pd.read_csv("../../seaborn-data-master/tips.csv")
fig = px.scatter(tips, x="total_bill", y="tip") # 散点图
pio.write_image(fig, "../../charts/template-default.png")
fig = px.scatter(tips, x="total_bill", y="tip", template="ggplot2")
pio.write_image(fig, "../../charts/template-ggplot2.png")
fig = px.scatter(tips, x="total_bill", y="tip", template="seaborn")
pio.write_image(fig, "../../charts/template-seaborn.png")
fig = px.scatter(tips, x="total_bill", y="tip", template="plotly_dark")
pio.write_image(fig, "../../charts/template-plotly_dark.png")
默认:
ggplot2

seaborn

plotly_dark
