Matplotlib绘制X轴断轴柱状图 保持刻度比例与柱宽一致
问题诊断
原有代码的核心问题有三个:
- 变量覆盖:先通过
plt.subplots()创建了两个轴并完成绘图,后续又调用plt.subplot()新建了两个空白轴覆盖了原有ax、ax2变量,最终渲染的是没有绘图内容的空白轴,导致数据不显示。 - 柱宽不一致:默认创建的等宽子图,和两个子图对应的X轴数值范围长度(左轴3个单位、右轴1个单位)不匹配,相同数值宽度的柱子在等宽子图里的物理显示宽度不一致。
- 显示异常:没有清理右侧子图的多余Y轴刻度,断点标记的绘制逻辑没有和子图拼接位置对齐,导致标记错位、多余刻度显示。
修正后可运行代码
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec x = [2, 3, 4, 10] y = [-10, -20, -25, -50] f = plt.figure(facecolor='w') # 子图宽度比严格匹配X轴显示范围的长度比:左轴范围长3单位,右轴范围长1单位,比例设为3:1保证刻度物理比例一致 gs = gridspec.GridSpec(1, 2, width_ratios=[3, 1]) ax = f.add_subplot(gs[0]) ax2 = f.add_subplot(gs[1], sharey=ax) # 统一在两个子图绘制柱状图 ax.bar(x, y) ax2.bar(x, y) # 设置X轴显示范围,中间跳过5-9区间 ax.set_xlim(1.5, 4.5) ax2.set_xlim(9.5, 10.5) # 隐藏拼接位置的边框 ax.spines['right'].set_visible(False) ax2.spines['left'].set_visible(False) # 统一Y轴只在左侧显示,隐藏右侧子图的Y轴刻度 ax.yaxis.tick_left() ax2.yaxis.set_tick_params(which='both', length=0) plt.setp(ax2.get_yticklabels(), visible=False) # 设置X轴刻度 ax.set_xticks([2, 3, 4]) ax2.set_xticks([10]) # 设置轴标签 ax.set_ylabel("Y-Axis") f.text(0.5, 0.04, "X-Axis", ha="center") # 绘制轴断点斜杠标记 d = 0.015 kwargs = dict(transform=ax.transAxes, color='k', clip_on=False) ax.plot((1 - d, 1 + d), (-d, +d), **kwargs) ax.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs) kwargs.update(transform=ax2.transAxes) ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs) ax2.plot((-d, +d), (-d, +d), **kwargs) plt.savefig("leaf.png", format="png", dpi=1000, bbox_inches="tight")
实现要点
- 统一刻度比例:子图宽度比和两个子图X轴数值范围的长度比严格对应(3:1),不需要手动调整柱宽参数,就能保证两个子图内X轴每单位数值对应的物理宽度完全一致,柱宽全程统一。
- 轴对象初始化逻辑调整:先通过gridspec创建好轴对象再绘图,从根源避免变量覆盖导致的绘图内容丢失问题。
- 冗余元素清理:关闭右侧子图的Y轴刻度和标签,断点斜杠基于轴相对坐标绘制,和子图拼接位置完全对齐,不会出现错位。
内容的提问来源于stack exchange,提问作者Wychh
相关产品推荐
相关产品推荐

