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
相关产品推荐
相关产品推荐

