Plotly子图X轴仅单图显示刻度问题求助
问题:子图仅单个显示X轴刻度
使用plot_data函数绘制垂直子图时,预期所有子图的X轴都显示刻度值,但实际只有一个子图显示刻度。
问题代码
def plot_data(data, filename): """ Plotting the data param data: data to plot. param filename: file name to write the output in. return: None. """ subplot_titles = [] for segment in data: subplot_titles.append( f"{segment.get('problem_id')} {segment.get('y_array_label')}({segment.get('x_array_label')})") subplot_titles_tuple = tuple(subplot_titles) fig = make_subplots(rows=len(data), cols=1, shared_xaxes=True, subplot_titles=subplot_titles_tuple) fig.update_layout(updatemenus = [ dict( buttons=[ dict(label="Linear", method="relayout", args=[{"yaxis.type": "linear"}]), dict(label="Log", method="relayout", args=[{"yaxis.type": "log"}]), ])]) for i, segment in enumerate(data): trace = go.Scatter(x=segment['x'], y=segment['y'], mode='lines', name=f"Plot {i + 1}") print('im here',segment['x'] ) fig.add_trace(trace,row=i+1,col=1) # Set subplot titles fig.update_layout(title=f"Plots for {filename}") # Set x-axis and y-axis titles according to segment data x_title = segment.get('x_array_label', 'RCM') # Default to 'X-axis' if 'x_array_label' is not present y_title = segment.get('y_array_label', 'Y-axis') # Default to 'Y-axis' if 'y_array_label' is not present fig.update_xaxes(title_text=x_title, row=i + 1, col=1) fig.update_yaxes(title_text=y_title, row=i + 1, col=1) # Add update menus to each subplot # change from Linear to Log fig.update_layout( updatemenus=[ dict( buttons=[ dict(label="Linear", method="relayout", args=[{"yaxis.type": "linear"}]), dict(label="Log", method="relayout", args=[{"yaxis.type": "log"}]), ], direction="down", showactive=True, x=1, xanchor="left", y=0.9, yanchor="top" ) ] ) # change xlim and ylim xlim_slider = widgets.FloatRangeSlider( value=[min(segment['x']), max(segment['x'])], # Initial limits based on data min=min(segment['x']), max=max(segment['x']), step=0.1, description='xlim:', continuous_update=False ) ylim_slider = widgets.FloatRangeSlider( value=[min(segment['y']), max(segment['y'])], # Initial limits based on data min=min(segment['y']), max=max(segment['y']), step=0.1, description='ylim:', continuous_update=False ) # Function to update xlim and ylim def update_plot(xlim, ylim): fig.update_xaxes(range=xlim) fig.update_yaxes(range=ylim) # Connect sliders to update function widgets.interactive(update_plot, xlim=xlim_slider, ylim=ylim_slider) # Show or save the plot plot_filename = f"{os.path.splitext(filename)[0]}_plots.html" plot_path = os.path.join(os.getcwd(), plot_filename) fig.write_html(plot_path) print(f"All plots saved in {plot_filename}")
原因分析
- 共享X轴默认行为:
make_subplots中设置shared_xaxes=True时,Plotly默认仅显示最底部子图的X轴刻度,其他子图隐藏刻度以避免重复。 - 重复布局覆盖:循环内多次调用
fig.update_layout会重复覆盖全局布局设置,虽不直接影响刻度,但属于冗余代码。 - 滑块更新逻辑缺陷:
update_plot函数中fig.update_xaxes(range=xlim)未指定子图行,会同时修改所有子图X轴范围,但不解决刻度显示问题。
解决方案
1. 强制所有子图显示X轴刻度
在循环遍历子图时,为每个X轴添加showticklabels=True参数,强制显示刻度:
# 在循环内的update_xaxes处修改 fig.update_xaxes(title_text=x_title, showticklabels=True, row=i + 1, col=1)
2. 优化共享轴配置(可选)
若需要保留共享轴联动但显示所有刻度,可将shared_xaxes设置为'all',并配合显示刻度:
# 修改make_subplots的参数 fig = make_subplots(rows=len(data), cols=1, shared_xaxes='all', subplot_titles=subplot_titles_tuple)
3. 清理冗余布局代码
将fig.update_layout(title=...)和updatemenus的设置移到循环外,避免重复覆盖:
# 循环结束后统一设置标题和更新菜单 fig.update_layout(title=f"Plots for {filename}") fig.update_layout( updatemenus=[ dict( buttons=[ dict(label="Linear", method="relayout", args=[{"yaxis.type": "linear"}]), dict(label="Log", method="relayout", args=[{"yaxis.type": "log"}]), ], direction="down", showactive=True, x=1, xanchor="left", y=0.9, yanchor="top" ) ] )
4. 修复滑块更新逻辑
让滑块能正确作用于所有子图的范围:
def update_plot(xlim, ylim): # 遍历所有子图更新范围 for row in range(1, len(data)+1): fig.update_xaxes(range=xlim, row=row, col=1) fig.update_yaxes(range=ylim, row=row, col=1)
内容的提问来源于stack exchange,提问作者Roba-Barham
相关产品推荐
相关产品推荐

