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

Pyplot多Y轴不同刻度绘图问题求助

如何在Matplotlib中创建多Y轴且各轴刻度独立的图表

问题描述

我想要绘制一张多Y轴、各轴刻度不同的可视化图表,在同一张图里用多个独立刻度的Y轴展示多条曲线。我写了一段Python代码,空图时效果符合预期,但加入数据后出现了问题:第i个轴会适配i+1轴的数据刻度,而非仅适配当前轴对应曲线的值,这也导致曲线出现不连续的情况。以下是我的代码:

fig, (ax, ax1, ax2, ax3, ax4, ax5) = plt.subplots(1, 6)
chartBox = ax1.get_position()
ax1.set_position([chartBox.x0-0.022, chartBox.y0, chartBox.width, chartBox.height])
chartBox = ax2.get_position()
ax2.set_position([chartBox.x0-0.044, chartBox.y0, chartBox.width, chartBox.height])
chartBox = ax3.get_position()
ax3.set_position([chartBox.x0-0.066, chartBox.y0, chartBox.width, chartBox.height])
chartBox = ax4.get_position()
ax4.set_position([chartBox.x0-0.088, chartBox.y0, chartBox.width, chartBox.height])
chartBox = ax5.get_position()
ax6=ax5.twinx()
ax5.set_position([chartBox.x0-0.112, chartBox.y0, chartBox.width, chartBox.height])
ax.set_xticks([])
ax1.set_xticks([])
ax2.set_xticks([])
ax3.set_xticks([])
ax4.set_xticks([])
ax5.set_xticks([])
ax6.set_xticks([])
Hyper=[0.785,0.890275,6.443702104245254 ]
Bayes=[0.789,0.88805,6.325708590132482 ]
Ax=[0.817,0.885175,6.133054804498614 ]
NG=[0.8,0.884825,6.290438322234702 ]
BOHB=[0.785,0.8876999999999999,6.173551552576356 ]
Ran=[0.787,0.884175,6.170678868638696 ]
Zoo=[0.795,0.884625,6.325670890740688 ]
j=0
tmp=ax
tmp.plot(Hyper[j:j+2])
tmp.plot(Bayes[j:j+2])
tmp.plot(Ax[j:j+2])
tmp.plot(NG[j:j+2])
tmp.plot(BOHB[j:j+2])
tmp.plot(Ran[j:j+2])
tmp.plot(Zoo[j:j+2])
tmp=ax1
j=1
tmp.plot(Hyper[j:j+2])
tmp.plot(Bayes[j:j+2])
tmp.plot(Ax[j:j+2])
tmp.plot(NG[j:j+2])
tmp.plot(BOHB[j:j+2])
tmp.plot(Ran[j:j+2])
tmp.plot(Zoo[j:j+2])
plt.show()

注:此处仅提供3个轴的数据,我认为适用于3个轴的解决方案同样可推广至7个轴。


解决方案

问题根源分析

你当前用多个独立子图重叠的方式模拟多Y轴,本质上是把多个分离的图表叠在一起。每个子图的x轴默认使用数据的索引(比如第一次plot时x是[0,1],第二次plot时x还是[0,1],但对应的数据实际位置应该是[1,2]),这就导致子图间x轴范围不匹配,进而出现刻度互相干扰、曲线错位的问题。

正确做法:使用孪生轴(twinx())

Matplotlib的标准多Y轴实现是基于同一个主轴创建孪生轴——它们共享x轴,Y轴完全独立,能各自设置刻度、范围和样式,完美解决你的需求。

以下是适配你数据的修正代码:

import matplotlib.pyplot as plt

# 准备数据
Hyper = [0.785, 0.890275, 6.443702104245254]
Bayes = [0.789, 0.88805, 6.325708590132482]
Ax = [0.817, 0.885175, 6.133054804498614]
NG = [0.8, 0.884825, 6.290438322234702]
BOHB = [0.785, 0.8876999999999999, 6.173551552576356]
Ran = [0.787, 0.884175, 6.170678868638696]
Zoo = [0.795, 0.884625, 6.325670890740688]
x = range(len(Hyper))  # 统一x轴,确保所有曲线对齐

# 创建主图
fig, ax = plt.subplots(figsize=(10, 6))

# 第一组曲线:使用主Y轴
lines = []
lines += ax.plot(x, Hyper, label='Hyper')
lines += ax.plot(x, Bayes, label='Bayes')
lines += ax.plot(x, Ax, label='Ax')
lines += ax.plot(x, NG, label='NG')
lines += ax.plot(x, BOHB, label='BOHB')
lines += ax.plot(x, Ran, label='Ran')
lines += ax.plot(x, Zoo, label='Zoo')
ax.set_ylabel('主Y轴刻度')
ax.tick_params(axis='y')

# 创建第二个孪生Y轴(独立刻度)
ax2 = ax.twinx()
# 示例:给这个轴单独绘制曲线(如果需要)
# ax2.plot(x, [val*10 for val in Hyper], label='Hyper (x10)', color='red')
ax2.set_ylabel('第二组Y轴刻度')
ax2.tick_params(axis='y')

# 创建第三个孪生Y轴,调整位置避免重叠
ax3 = ax.twinx()
ax3.spines['right'].set_position(('axes', 1.15))  # 轴位置右移15%
# ax3.plot(x, [val/10 for val in Hyper], label='Hyper (/10)', color='green')
ax3.set_ylabel('第三组Y轴刻度')
ax3.tick_params(axis='y')

# 合并所有图例,避免重复
labels = [line.get_label() for line in lines]
ax.legend(lines, labels, loc='upper left')

plt.tight_layout()
plt.show()

核心要点

  1. 统一x轴:所有曲线使用同一个x轴数据,保证数据点完全对齐,不会出现错位。
  2. 孪生轴独立性:twinx()创建的轴和主轴共享x轴,但Y轴完全独立,每个轴的刻度、范围、颜色都可以单独设置,不会互相干扰。
  3. 多轴位置调整:当创建3个及以上右侧Y轴时,需要通过spines['right'].set_position调整轴的位置,避免轴标签重叠。参数('axes', 1.15)表示轴位于主图右侧15%的位置,可根据轴的数量调整数值(比如第4个轴用1.3,第5个用1.45等)。
  4. 手动控制Y轴范围:如果需要固定某个轴的刻度范围,可以用ax.set_ylim(min_val, max_val),让轴只适配对应曲线的数据。

扩展到7个Y轴

如果需要7个独立Y轴,只需重复创建孪生轴并依次调整位置即可:

# 第4个轴
ax4 = ax.twinx()
ax4.spines['right'].set_position(('axes', 1.3))
ax4.set_ylabel('第四组Y轴刻度')

# 第5个轴
ax5 = ax.twinx()
ax5.spines['right'].set_position(('axes', 1.45))
ax5.set_ylabel('第五组Y轴刻度')

# 第6、7个轴以此类推,逐步增加位置参数

这样每个Y轴都会独立适配自己的曲线数据,彻底解决你之前遇到的刻度干扰和曲线不连续问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:50:24