You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plotly-Python:如何单独设置子图共享y轴范围

Plotly多子图中单独设置某行共享y轴范围的问题解决

问题描述

在Plotly-Python的多子图中尝试手动设置某一行共享y轴的范围,但操作同时影响了其他行的y轴范围。示例代码如下:

import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.io as pio

pio.renderers.default = "browser"

np.random.seed(42)

N = 20
nrows, ncols, ntraces = 3, 2, 3

fig = make_subplots(
    rows=nrows, cols=ncols,
    shared_xaxes=True, shared_yaxes=True,
)

for r in range(nrows):
    scale = 1 / 10 ** r
    for c in range(ncols):
        for t in range(ntraces):
            y = np.random.randn(N) * scale
            fig.add_trace(
                row=r + 1, col=c + 1,
                trace=go.Scatter(y=y, mode="markers+lines", name=f"trace {t}")
            )
fig.update_layout(showlegend=False)
fig.show()

运行后生成每行共享y轴的3x2子图,执行fig.update_yaxes(range=[-2, 2], row=1, col=1)设置第一行y轴范围后,其他行y轴范围被自动改为[-1,4],尝试range=[None, None]、rangemode='normal'等方式恢复均无效,需实现仅单独设置某一个共享y轴的范围。

核心原因

shared_yaxes=True会让同一行的所有子图绑定到同一个y轴对象,修改该对象的范围参数会同步影响所有关联的子图,导致其他行的y轴范围被意外修改。

解决方案

方案一:预先存储数据,单独设置各行范围

创建子图时保持行内共享y轴,同时存储每行的所有y数据,设置目标行范围后,为其他行重新计算并设置基于自身数据的自动范围:

import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.io as pio

pio.renderers.default = "browser"

np.random.seed(42)

N = 20
nrows, ncols, ntraces = 3, 2, 3

fig = make_subplots(
    rows=nrows, cols=ncols,
    shared_xaxes=True,
    shared_yaxes='rows'
)

# 存储每行的所有y数据,用于后续计算范围
row_y_datasets = [[] for _ in range(nrows)]

for r in range(nrows):
    scale = 1 / 10 ** r
    for c in range(ncols):
        for t in range(ntraces):
            y = np.random.randn(N) * scale
            row_y_datasets[r].extend(y)
            fig.add_trace(
                row=r + 1, col=c + 1,
                trace=go.Scatter(y=y, mode="markers+lines", name=f"trace {t}")
            )

# 设置第一行y轴的自定义范围
fig.update_yaxes(range=[-2, 2], row=1, col=1)

# 为其他行计算并设置适配自身数据的范围(添加10%的边距提升美观度)
for row_idx in range(2, nrows + 1):
    y_vals = row_y_datasets[row_idx - 1]
    y_min, y_max = min(y_vals), max(y_vals)
    margin = (y_max - y_min) * 0.1
    fig.update_yaxes(range=[y_min - margin, y_max + margin], row=row_idx, col=1)

fig.update_layout(showlegend=False)
fig.show()

方案二:取消目标行的y轴共享关联

将目标行的子图y轴从共享组中分离,使其独立,再设置自定义范围,同时保持其他行的共享状态:

import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.io as pio

pio.renderers.default = "browser"

np.random.seed(42)

N = 20
nrows, ncols, ntraces = 3, 2, 3

fig = make_subplots(
    rows=nrows, cols=ncols,
    shared_xaxes=True, shared_yaxes=True,
)

for r in range(nrows):
    scale = 1 / 10 ** r
    for c in range(ncols):
        for t in range(ntraces):
            y = np.random.randn(N) * scale
            fig.add_trace(
                row=r + 1, col=c + 1,
                trace=go.Scatter(y=y, mode="markers+lines", name=f"trace {t}")
            )

# 分离第一行的两个y轴,取消共享关联
first_row_yaxis_left = fig.layout.yaxis
first_row_yaxis_right = fig.layout.yaxis2

# 为两个y轴设置相同的域范围,保持视觉上的对齐
first_row_yaxis_left.domain = [0.67, 1.0]
first_row_yaxis_right.domain = [0.67, 1.0]
# 将右侧y轴绑定到对应列的x轴,实现独立
first_row_yaxis_right.anchor = 'x2'
# 隐藏右侧y轴的刻度标签,保持原有的视觉简洁性
first_row_yaxis_right.showticklabels = False

# 设置第一行左侧y轴的自定义范围
fig.update_yaxes(range=[-2, 2], row=1, col=1)

fig.update_layout(showlegend=False)
fig.show()

内容的提问来源于stack exchange,提问作者Jon Nir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:37:33