plotly 绘制子图(subplots)

划分子图 subplots

import plotly.io as pio
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np

# 设置plotly默认主题
pio.templates.default = 'plotly_white'

# 设置pandas打印时显示所有列
pd.set_option('display.max_columns', None)

make_subplots 常用参数介绍及示例

详细参数见:https://plotly.com/python-api-reference/plotly.subplots.html#subplots

  • rows:子图网格中的行数。
    • 大于0的整数,默认为1
  • cols:子图网格中的列数。
    • 大于0的整数,默认为1
  • shared_xaxes:为2D笛卡尔坐标系的子图分配共享x坐标轴。
    • 布尔类型或字符串类型,默认值为 FalseTrue'columns' 表示同一列子图共享坐标轴;'rows' 表示同一行子图共享坐标轴;'all' 表示所有子图共享坐标轴
  • shared_yaxes:为2D笛卡尔坐标系的子图分配共享y坐标轴。
    • 布尔类型或字符串类型,默认值为 False'columns' 表示同一列子图共享坐标轴;True'rows' 表示同一行子图共享坐标轴;'all' 表示所有子图共享坐标轴
  • horizontal_spacing:设置每列子图之间的间隔,对所有列应用。
    • 必须为 0~1 之间的浮点数,默认值为0.2
  • vertical_spacing:设置每行子图之间的间隔,对所有行应用。
    • 必须为 0~1 之间的浮点数,默认值为0.3
  • subplot_titles:每个子图的标题,按照行优先的顺序(从左到右,从上到下)
    • 字符串列表 或 None(默认值),列表长度必须等于子图个数(不一定等于 rows * cols),如果不想为其中某个子图设置标题,只需将列表中对应位置的标题设置为 "" (空字符串)。
  • specs:设置每个子图的规格:子图类型、行/列跨度和间隔。
    • specs 参数传入一个二维列表,列表中的元素为字典。二维列表的维度为 rows * cols,每个位置对应一个子图。如果想删除某个位置的子图,只需将二维列表中对应位置的值设置为 None
    • specs 中的每个条目都是一个字典,可用的参数为:
    • type:子图的类型(字符串类型,默认值为 'xy'),可以为:
      1. 'xy':2D 笛卡尔坐标系,适用于 scatter、bar等图表
      2. 'scene':3D 笛卡尔坐标系,适用于 scatter3d、cone等图表
      3. 'polar':极坐标系,适用于 scatterpolar、barpolar等图表
      4. 'ternary':三元坐标,适用于 scatterternary 等图表
      5. 'mapbox':地图,适用于 scattermapbox等图表
      6. 'domain':独特位置的子图,适用于 pie、parcoords、parcats等图表
      7. 图表类型名:可以使用要绘制的图表名,进而自动推断子图的类型,比如 'type': 'bar'
    • secondary_y:是否创建第二纵坐标轴,第二纵坐标位于图表的右侧,只有 tpye='xy' 时才可以使用。布尔类型。
    • colspan:该子图所占的列数,默认为1,大于0,小于 cols 的整数。
    • rowspan:该子图所占的行数,默认为1,大于0,小于 rows 的整数。
    • l:填充(padding)左侧格子(cell),浮点数,默认为 0.0
    • r:填充(padding)右侧格子(cell),浮点数,默认为 0.0
    • t:填充(padding)顶部格子(cell),浮点数,默认为 0.0
    • b:填充(padding)底部格子(cell),浮点数,默认为 0.0
    • 例如:specs=[[{}, {}], [{‘colspan’ : 2}, None]],specs=[[{‘rowspan’ : 2}, {}], [None, {}]]
  • insets:嵌入图的规格,嵌入图是覆盖在网格子图上的子图。
    • 传入字典列表 或 None(默认值),insets 中的每个条目都是一个字典,可用的参数为:
      • cell:默认值为 (1, 1),元组类型 (row, col) 表示子图的索引,以便将插入的坐标轴覆盖在上面
      • type:子图类型。字符串类型,默认值为 'xy',与 specstype一样。
      • l:填充嵌入图左侧,以格子(该子图的网格)宽度为标准,浮点数,默认为0.0
      • w:嵌入图的宽度,以格子(该子图的网格)宽度为标准,浮点数 或 'to_end'(默认值),表示网格右侧
      • b:填充嵌入图底部,以格子(该子图的网格)高度为标准,浮点数,默认为0.0
      • h:嵌入图的高度,以格子(该子图的网格)高度为标准,浮点数 或 'to_end'(默认值),表示网格顶部
  • column_widths:设置列宽度,列表中的长度为 cols 的每一列的相对宽度,列表的值会被标准化(缩放为0~1),并用于为各列子图分配整体宽度(不包含填充(padding))
  • row_heights:设置行高度,列表中的长度为 'rows' 的每一行的相对高度。
  • column_titles:每一列子图的标题,在每一列最上面的子图上面放置一个标题。
    • 字符串列表 或 None(默认值),如果某列不想要标题,可以将对应位置设置为 ''(空字符串)
  • row_titles:每一行子图的标题,在每一行最右侧的子图右边放置一个标题。
    • 字符串列表 或 None(默认值),如果某列不想要标题,可以将对应位置设置为 ''(空字符串)
  • x_title:放置在最下方正中间的标题,字符串或 None(默认值)
  • y_title:放置在最左侧正中间的标题,字符串或 None(默认值)
注:以下所有使用 make_subplots 的代码,均可使用 fig = go.Figure().set_subplots() 替代
参数完全相同,不必导入 from plotly.subplots import make_subplots
# 创建一个3行1列的子图
# 等价于 fig = go.Figure().set_subplots(rows=3, cols=1)
fig = make_subplots(rows=3, cols=1)

# 使用row、col参数,为指定子图添加图表
fig.append_trace(go.Scatter(
    x=[3, 4, 5],
    y=[1000, 1100, 1200],
), row=1, col=1)

fig.append_trace(go.Scatter(
    x=[2, 3, 4],
    y=[100, 110, 120],
), row=2, col=1)

fig.append_trace(go.Scatter(
    x=[0, 1, 2],
    y=[10, 11, 12]
), row=3, col=1)


fig.update_layout(height=600, width=600, title_text="Stacked Subplots")

fig.write_image('../pic/subplots_1.png', scale=10)
fig.show()

在这里插入图片描述

# 自定义宽度
fig = make_subplots(rows=1, cols=2, column_widths=[0.7, 0.3])

fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
              row=1, col=1)

fig.add_trace(go.Scatter(x=[20, 30, 40], y=[50, 60, 70]),
              row=1, col=2)

fig.write_image('../pic/subplots_2.png', scale=10)
fig.show()

在这里插入图片描述

# 自定义每个子图的坐标轴属性
fig = make_subplots(
    rows=2, cols=2, subplot_titles=("Plot 1", "Plot 2", "Plot 3", "Plot 4")
)

# Add traces
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]), row=1, col=1)
fig.add_trace(go.Scatter(x=[20, 30, 40], y=[50, 60, 70]), row=1, col=2)
fig.add_trace(go.Scatter(x=[300, 400, 500], y=[600, 700, 800]), row=2, col=1)
fig.add_trace(go.Scatter(x=[4000, 5000, 6000], y=[7000, 8000, 9000]), row=2, col=2)

# Update xaxis properties
# 使用 row、col参数指定设置某个子图的坐标轴属性
'''
也可以使用 fig.update_layout(xaxis={...}, xaxis2={...}, xaxis3={...} ... , yaxis={...} ...)
'''
fig.update_xaxes(title_text="xaxis 1 title", row=1, col=1)
fig.update_xaxes(title_text="xaxis 2 title", range=[10, 50], row=1, col=2)
fig.update_xaxes(title_text="xaxis 3 title", showgrid=False, row=2, col=1)
fig.update_xaxes(title_text="xaxis 4 title", type="log", row=2, col=2)

# Update yaxis properties
fig.update_yaxes(title_text="yaxis 1 title", row=1, col=1)
fig.update_yaxes(title_text="yaxis 2 title", range=[40, 80], row=1, col=2)
fig.update_yaxes(title_text="yaxis 3 title", showgrid=False, row=2, col=1)
fig.update_yaxes(title_text="yaxis 4 title", row=2, col=2)

# Update title and height
fig.update_layout(title_text="Customizing Subplot Axes", height=700)

fig.write_image('../pic/subplots_3.png', scale=10)
fig.show()

在这里插入图片描述

# 共享 x 坐标轴
fig = make_subplots(rows=3, cols=1,
                    shared_xaxes=True,
                    vertical_spacing=0.05)

fig.add_trace(go.Scatter(x=[0, 1, 2], y=[10, 11, 12]),
              row=3, col=1)

fig.add_trace(go.Scatter(x=[2, 3, 4], y=[100, 110, 120]),
              row=2, col=1)

fig.add_trace(go.Scatter(x=[3, 4, 5], y=[1000, 1100, 1200]),
              row=1, col=1)

fig.update_layout(height=600, width=600,
                  title_text="Stacked Subplots with Shared X-Axes")

fig.write_image('../pic/subplots_4.png', scale=10)
fig.show()

在这里插入图片描述

# 共享y轴
fig = make_subplots(rows=2, cols=2, shared_yaxes=True)

fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 3, 4]),
              row=1, col=1)

fig.add_trace(go.Scatter(x=[20, 30, 40], y=[5, 5, 5]),
              row=1, col=2)

fig.add_trace(go.Scatter(x=[2, 3, 4], y=[600, 700, 800]),
              row=2, col=1)

fig.add_trace(go.Scatter(x=[4000, 5000, 6000], y=[7000, 8000, 9000]),
              row=2, col=2)

fig.update_layout(height=600, width=600,
                  title_text="Multiple Subplots with Shared Y-Axes")

fig.write_image('../pic/subplots_5.png', scale=10)
fig.show()

在这里插入图片描述

# 自定义子图大小
fig = make_subplots(
    rows=2, cols=2,
    specs=[[{}, {}],
           [{"colspan": 2}, None]],
    subplot_titles=("First Subplot","Second Subplot", "Third Subplot"))

fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
                 row=1, col=1)

fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
                 row=1, col=2)
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 1, 2]),
                 row=2, col=1)

fig.update_layout(showlegend=False, title_text="Specs with Subplot Title")

fig.write_image('../pic/subplots_6.png', scale=10)
fig.show()

在这里插入图片描述

fig = make_subplots(
    rows=5, cols=2,
    specs=[[{}, {"rowspan": 2}],
           [{}, None],
           [{"rowspan": 2, "colspan": 2}, None],
           [None, None],
           [{}, {}]],
    print_grid=True)

fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2], name="(1,1)"), row=1, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2], name="(1,2)"), row=1, col=2)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2], name="(2,1)"), row=2, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2], name="(3,1)"), row=3, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2], name="(5,1)"), row=5, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2], name="(5,2)"), row=5, col=2)

fig.update_layout(height=600, width=600, title_text="specs examples")

fig.write_image('../pic/subplots_7.png', scale=10)
fig.show()

在这里插入图片描述

# 子图类型
fig = make_subplots(
    rows=2, cols=2,
    specs=[[{"type": "xy"}, {"type": "polar"}],
           [{"type": "domain"}, {"type": "scene"}]],
)
'''
也可以为:specs=[[{'type': 'bar'}, {'type': 'barpolar'}],
                [{'type': 'pie'}, {'type': 'scatter3d'}]]
'''

fig.add_trace(go.Bar(y=[2, 3, 1]),
              row=1, col=1)

fig.add_trace(go.Barpolar(theta=[0, 45, 90], r=[2, 3, 1]),
              row=1, col=2)

fig.add_trace(go.Pie(values=[2, 3, 1]),
              row=2, col=1)

fig.add_trace(go.Scatter3d(x=[2, 3, 1], y=[0, 0, 0],
                           z=[0.5, 1, 2], mode="lines"),
              row=2, col=2)

fig.update_layout(height=700, showlegend=False)

fig.write_image('../pic/subplots_8.png', scale=10)
fig.show()

在这里插入图片描述

# 子图开启第二纵轴
fig = make_subplots(
    rows=2, cols=2,
    specs=[[{"type": "xy", 'secondary_y': True}, {"type": "polar"}],
           [{"type": "domain"}, {"type": "scene"}]],
    y_title='title'
)
'''
也可以为:specs=[[{'type': 'bar'}, {'type': 'barpolar'}],
                [{'type': 'pie'}, {'type': 'scatter3d'}]]
'''

# 使用 secondary_y 参数选择该图相对的 y轴坐标
fig.add_trace(go.Bar(y=[2, 3, 1]),
              row=1, col=1, secondary_y=False)
fig.add_trace(go.Scatter(x=[0, 1, 2], y=[4, 10, 7]),
              row=1, col=1, secondary_y=True)

fig.add_trace(go.Barpolar(theta=[0, 45, 90], r=[2, 3, 1]),
              row=1, col=2)

fig.add_trace(go.Pie(values=[2, 3, 1]),
              row=2, col=1)

fig.add_trace(go.Scatter3d(x=[2, 3, 1], y=[0, 0, 0],
                           z=[0.5, 1, 2], mode="lines"),
              row=2, col=2)

fig.update_layout(height=700, showlegend=False)

fig.write_image('../pic/subplots_9.png', scale=10)
fig.show()

在这里插入图片描述

# 绘制嵌入图
fig = make_subplots(
    rows=1, cols=2,
    insets=[{'cell': (1, 1), 'type': 'xy', 
            'l':0.5, 'w': 0.4, 'b':0.5, 'h':0.3}],
)           

# print(fig)

fig.add_trace(go.Scatter(
    x=[1, 2, 3, 4], y=[10, 7, 4, 6],
), row=1, col=1)


fig.add_trace(go.Scatter(
    x=[1, 2, 3, 4], y=[10, 13, 4, 6],
), row=1, col=2)

# 嵌入图需要指明绘制的坐标轴,可以使用 print(fig) 查看所有坐标轴
fig.add_trace(go.Scatter(
    x=[1, 2, 3, 4], y=[10, 13, 4, 6],
    xaxis='x3', yaxis='y3'
))

fig.update_layout(showlegend=False)

fig.write_image('../pic/subplots_10.png', scale=10)
fig.show()

在这里插入图片描述

  • 11
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值