Matplotlib同图绘制连续双折线并设置不同X轴标签的实现问题
问题描述
想要在同一张图里画两条连续折线,给它们设置不同的X轴标签,同时让图表前半部分也显示网格。
原代码如下:
plt.xlabel('\# Basis') plt.ylabel('Energy') plt.grid(True) plt.plot(np.arange(1,size_basis+1), means_SGD, label='SGD step') plt.fill_between(np.arange(1,size_basis+1), max_SGD, min_SGD, alpha=0.5) plt.legend() plt.xlabel('\# Step') plt.xticks(np.arange(10,59), np.arange(1, 50)) plt.plot(np.arange(10, 59), means_s, label='SGD full') plt.fill_between(np.arange(10, 59), max_v_s, min_v_s, alpha=0.5) plt.legend()
当前存在的问题:
- 后设置的X轴标签会覆盖前一个,无法同时显示两个X轴的标签
- 图表前半部分的网格没有正常显示
- 两条折线的X轴刻度没有达到分段对应期望的效果
期望实现的效果:
- 图表拥有两个独立的X轴,分别对应“# Basis”和“# Step”
- 两条折线连续衔接,各自匹配正确的X轴刻度
- 整个图表区域都显示网格
解决方案
通过Matplotlib的双X轴功能来实现需求,同时调整网格和折线绘制逻辑,修改后的代码如下:
import matplotlib.pyplot as plt import numpy as np # 替换成你的真实数据,以下是模拟示例 size_basis = 10 means_SGD = np.random.rand(size_basis) max_SGD = means_SGD + 0.1 min_SGD = means_SGD - 0.1 means_s = np.random.rand(49) max_v_s = means_s + 0.1 min_v_s = means_s - 0.1 # 创建主画布和主X轴 fig, ax1 = plt.subplots() # 绘制第一条折线(SGD step),对应主X轴# Basis x1 = np.arange(1, size_basis + 1) ax1.plot(x1, means_SGD, label='SGD step') ax1.fill_between(x1, max_SGD, min_SGD, alpha=0.5) ax1.set_xlabel('# Basis') ax1.set_ylabel('Energy') # 开启全区域网格,which='both'包含主副刻度,axis='both'覆盖XY轴 ax1.grid(True, which='both', axis='both') # 调整主X轴范围,覆盖两条折线的所有X值 ax1.set_xlim(1, 58) # 绘制第二条折线(SGD full),对应X轴10到58 x2 = np.arange(10, 59) ax1.plot(x2, means_s, label='SGD full') ax1.fill_between(x2, max_v_s, min_v_s, alpha=0.5) # 创建副X轴,共享Y轴,用于显示# Step ax2 = ax1.twiny() # 副X轴范围和主X轴保持一致 ax2.set_xlim(ax1.get_xlim()) # 设置副X轴的刻度位置和对应标签 ax2.set_xticks(np.arange(10, 59)) ax2.set_xticklabels(np.arange(1, 50)) ax2.set_xlabel('# Step') # 合并图例并调整位置 ax1.legend(loc='upper right') plt.tight_layout() plt.show()
关键调整说明:
- 用
twiny()创建共享Y轴的副X轴,确保两个X轴的范围完全匹配,避免错位 - 主X轴设置为覆盖两条折线的全部X区间(1到58),保证网格能铺满整个图表区域
- 副X轴的刻度位置对应第二条折线的起始点,标签映射为“# Step”的编号
- 网格参数
which='both'和axis='both'确保主副刻度、XY轴方向都显示网格
内容的提问来源于stack exchange,提问作者Paolo Recchia
相关产品推荐
相关产品推荐

