Search code examples
pythonpython-3.xplotly

Setting Axis Range for Subplot in Plotly-Python


I am trying to manually set the range of one (shared) y-axis in a plotly multi-plot figure, but for some reason, it also affects the range of the other y-axes.
Take a look at this example. I'll start by creating a 3x2 figure, with a shared y-axis per row.

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

This generates the following figure: generic example for multi-plot figure

Now I want to manually set the range only for the first row, so I do:

fig.update_yaxes(range=[-2, 2], row=1, col=1)
fig.show()

This indeed sets the range as required. Problem is, this upsets all other axes as well, changing their range to some automatic value ([-1, 4]): Wrong Range

I tried manually setting the range of the other rows using various combinations of range and rangemode='normal', for example:

fig.update_yaxes(range=[None, None], row=2, col=1)
fig.update_yaxes(range=None, row=2, col=1)
fig.update_yaxes(rangemode='normal', row=2, col=1)

Nothing seems to work...
How do I manually set the y-axis range only for one of the axes?


Solution

  • It looks like a bug, likely caused by having both shared_xaxes=True and shared_yaxes=True.

    I don't think you can update only one yaxis (since they are shared) but you can still update pairs of y axes (on the same row) and set autorange=True to prevent that weird behavior for those axes that should not have their range updated :

    fig.update_yaxes(range=[-2, 2], row=1)  # 'y'  and 'y2'
    fig.update_yaxes(autorange=True, row=2) # 'y3' and 'y4'
    fig.update_yaxes(autorange=True, row=3) # 'y5' and 'y6'
    

    You can also do that in one call by specifying axis ids of any pair :

    fig.update_layout(
        yaxis_range=[-2, 2],    # 'y'  and 'y2'
        yaxis3_autorange=True,  # 'y3' and 'y4'
        yaxis5_autorange=True,  # 'y5' and 'y6'
    )