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

如何使Plotly双Y轴零点对齐且仅调整刻度标签?

Plotly双Y轴零点对齐实现(仅调整刻度标签)

需求:绘制包含柱状图和折线图的双Y轴图表,要求右侧Y轴(对应折线图)与左侧Y轴(对应柱状图)零点对齐,仅调整Y轴刻度标签,不修改原始数据展示。

原代码:

bar_trace = go.Bar(x=line_s['Year/Quarter'], y=line_s['CUR (€)'], name='CUR (€)')

line_trace1 = go.Scatter(x=line_s['Year/Quarter'], y=line_s['CUR PP'], name='CUR PP', yaxis='y2', 
                        mode='lines+markers', line=dict(color='orange'))

layout = go.Layout(title='test', 
                   yaxis=dict(title='CUR (€)'),
                   yaxis2=dict(title='CUR PP (%)', overlaying='y', side='right', tickmode="sync"),
                   legend=dict(x=1.06))

fig = go.Figure(data=[bar_trace, line_trace1], layout=layout)

fig.show()

图表示例:
图表示例

解决方案

Plotly自带的tickmode="sync"仅同步刻度数量,无法实现零点对齐。要达成需求,需通过计算两个Y轴数据的极值,手动调整轴的range参数,让零点在同一水平线上。

步骤与修改后代码

  1. 获取两组数据的极值,计算零点到两端的范围比例
  2. 根据比例调整右侧Y轴的范围,确保与左侧Y轴零点对齐

完整代码如下:

import plotly.graph_objects as go

# 假设line_s是已加载的数据集
bar_trace = go.Bar(x=line_s['Year/Quarter'], y=line_s['CUR (€)'], name='CUR (€)')
line_trace1 = go.Scatter(x=line_s['Year/Quarter'], y=line_s['CUR PP'], name='CUR PP', yaxis='y2', 
                        mode='lines+markers', line=dict(color='orange'))

# 获取两个系列的Y轴极值
y1_min = line_s['CUR (€)'].min()
y1_max = line_s['CUR (€)'].max()
y2_min = line_s['CUR PP'].min()
y2_max = line_s['CUR PP'].max()

# 计算左侧Y轴正负方向的范围(以零点为基准)
y1_range_neg = abs(y1_min) if y1_min < 0 else 0
y1_range_pos = y1_max if y1_max > 0 else 0

# 计算右侧Y轴正负方向的范围
y2_range_neg = abs(y2_min) if y2_min < 0 else 0
y2_range_pos = y2_max if y2_max > 0 else 0

# 计算比例,确保零点对齐
ratio_neg = y1_range_neg / y2_range_neg if y2_range_neg != 0 else 1
ratio_pos = y1_range_pos / y2_range_pos if y2_range_pos != 0 else 1

# 确定右侧Y轴的新范围
if y2_range_neg > 0 and y2_range_pos > 0:
    target_ratio = max(ratio_neg, ratio_pos)
    y2_new_min = -y1_range_neg / target_ratio
    y2_new_max = y1_range_pos / target_ratio
elif y2_range_neg > 0:
    y2_new_min = -y1_range_neg / ratio_neg
    y2_new_max = 0
else:
    y2_new_min = 0
    y2_new_max = y1_range_pos / ratio_pos

# 更新布局
layout = go.Layout(title='test', 
                   yaxis=dict(title='CUR (€)', range=[-y1_range_neg, y1_range_pos]),
                   yaxis2=dict(title='CUR PP (%)', overlaying='y', side='right', range=[y2_new_min, y2_new_max]),
                   legend=dict(x=1.06))

fig = go.Figure(data=[bar_trace, line_trace1], layout=layout)
fig.show()

说明

  • 该方案仅调整Y轴的刻度范围和标签,完全不修改原始数据的展示
  • 通过计算正负范围的比例,确保两个Y轴的零点精确对齐
  • 兼容单侧有负值、双侧都有负值或无负值的多种数据场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:53:17