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

Plotly垂直子图共用X轴:保留刻度标签并实现跨子图Spike Line

问题:保留X轴刻度同时实现跨子图Spike Line显示

我需要垂直堆叠多个共用X轴的图表,鼠标悬停时Spike Line能贯穿所有子图,同时希望统一悬浮提示显示所有子图数据。但根据Plotly的GitHub Issue,统一悬浮提示功能暂未纳入开发规划。

我编写了如下代码:

#!/usr/local/bin/python3

import plotly.graph_objects as go
from plotly.subplots import make_subplots

reference_distance = [0, 1, 2, 3, 4]
compare_distance = [0, 1.5, 2.5, 3.5, 4.5]
reference_time = [0, 1, 3, 5, 6]
reference_speed = [100, 200, 300, 400, 500]
compare_speed = [50, 100, 150, 200, 250]

delta_t = [-1, -2, -3, -4, -5]

base = [0] * len(delta_t)

fig = go.Figure()

fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0)

fig.add_trace(
    go.Scatter(
        x=compare_distance,
        y=base,
        name='Reference Delta',
        hoverinfo='skip'
    ),
    row=1,
    col=1
)

fig.add_trace(
    go.Scatter(
        x=compare_distance,
        y=delta_t,
        name='Compare Delta',
        hovertemplate='Delta: %{y}<extra></extra>'
    ),
    row=1,
    col=1
)

fig.add_trace(
    go.Scatter(
        x=reference_distance,
        y=reference_speed,
        name='Reference',
        meta='Reference',
        hovertemplate='<b>%{meta}</b><br>Distance: %{x}<br>Speed: %{y}<extra></extra>'
    ),
    row=2,
    col=1
)

fig.add_trace(
    go.Scatter(
        x=compare_distance,
        y=compare_speed,
        name='Comapre',
        meta='Comapre',
        hovertemplate='<b>%{meta}</b><br>Distance: %{x}<br>Speed: %{y}<extra></extra>'
    ),
    row=2,
    col=1
)

fig.update_traces(mode="lines", xaxis="x")

fig.update_xaxes(
    showspikes=True,
    spikecolor="grey",
    spikesnap="cursor",
    spikemode="across",
    hoverformat="none",
)
fig.update_yaxes(title_text="Delta (Seconds)", row=1, col=1)
fig.update_yaxes(title_text="Speed (MPH)", row=2, col=1)
fig.update_layout(
    spikedistance=10000,
    hoverdistance=10000,
    hovermode="x unified",
    title="Delta T and Speed",
    xaxis_title="Distance (Miles)",
    legend_title="Runs"
)

fig.show()

我发现只有在update_traces中添加xaxis="x"(xaxis="x1"效果相同)后,Spike Line才能覆盖所有子图,但这会导致X轴的刻度和标签消失。请问如何在保留X轴刻度与标签的同时,实现Spike Line跨所有子图显示?

  • 无xaxis="x"时的效果:Spike Line仅在当前子图显示,X轴刻度正常
  • 有xaxis="x"时的效果:Spike Line跨所有子图,但X轴刻度和标签消失

解决方案

问题根源是update_traces(xaxis="x")强制所有trace使用底层默认的x轴,覆盖了子图自动生成的x1(第二行)和x2(第一行)轴配置,导致共用X轴的刻度丢失。正确做法是利用子图共用X轴的特性,结合spike参数配置实现需求:

修改后的代码如下:

#!/usr/local/bin/python3

import plotly.graph_objects as go
from plotly.subplots import make_subplots

reference_distance = [0, 1, 2, 3, 4]
compare_distance = [0, 1.5, 2.5, 3.5, 4.5]
reference_time = [0, 1, 3, 5, 6]
reference_speed = [100, 200, 300, 400, 500]
compare_speed = [50, 100, 150, 200, 250]

delta_t = [-1, -2, -3, -4, -5]

base = [0] * len(delta_t)

# 保留共用X轴配置
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0)

fig.add_trace(
    go.Scatter(
        x=compare_distance,
        y=base,
        name='Reference Delta',
        hoverinfo='skip'
    ),
    row=1,
    col=1
)

fig.add_trace(
    go.Scatter(
        x=compare_distance,
        y=delta_t,
        name='Compare Delta',
        hovertemplate='Delta: %{y}<extra></extra>'
    ),
    row=1,
    col=1
)

fig.add_trace(
    go.Scatter(
        x=reference_distance,
        y=reference_speed,
        name='Reference',
        meta='Reference',
        hovertemplate='<b>%{meta}</b><br>Distance: %{x}<br>Speed: %{y}<extra></extra>'
    ),
    row=2,
    col=1
)

fig.add_trace(
    go.Scatter(
        x=compare_distance,
        y=compare_speed,
        name='Compare',
        meta='Compare',
        hovertemplate='<b>%{meta}</b><br>Distance: %{x}<br>Speed: %{y}<extra></extra>'
    ),
    row=2,
    col=1
)

# 移除xaxis="x",仅保留线条模式设置
fig.update_traces(mode="lines")

# 给所有X轴配置spike参数,共用X轴时仅最下方X轴显示刻度
fig.update_xaxes(
    showspikes=True,
    spikecolor="grey",
    spikesnap="cursor",
    spikemode="across",
    hoverformat="none",
    # 显式确保刻度可见
    showticklabels=True
)
fig.update_yaxes(title_text="Delta (Seconds)", row=1, col=1)
fig.update_yaxes(title_text="Speed (MPH)", row=2, col=1)
fig.update_layout(
    spikedistance=10000,
    hoverdistance=10000,
    hovermode="x unified",
    title="Delta T and Speed",
    xaxis_title="Distance (Miles)",
    legend_title="Runs"
)

fig.show()

关键修改点:

  1. 移除update_traces中的xaxis="x",避免覆盖子图自动生成的X轴配置
  2. 显式设置update_xaxes(showticklabels=True),确保X轴刻度正常显示
  3. 利用shared_xaxes=True和spikemode="across"的组合,让Spike Line自动贯穿所有共用X轴的子图
  4. 修正原代码中"Comapre"的拼写错误

修改后即可同时保留X轴刻度标签,实现Spike Line跨子图显示的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:33:23