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

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}")

原因分析

  1. 共享X轴默认行为:make_subplots中设置shared_xaxes=True时,Plotly默认仅显示最底部子图的X轴刻度,其他子图隐藏刻度以避免重复。
  2. 重复布局覆盖:循环内多次调用fig.update_layout会重复覆盖全局布局设置,虽不直接影响刻度,但属于冗余代码。
  3. 滑块更新逻辑缺陷: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 21:27:05