matplotlib中ax.axvspan绘图无显示无报错问题求解
matplotlib axvspan 高亮区域不显示问题排查解决
问题现象
调用ax.axvspan()添加垂直区间高亮时无报错,但目标区域不在生成图片中显示,原始运行效果如下:
原始代码片段:
fig = plt.figure(figsize=(15, 6)) ax = fig.add_subplot(111) xtime = np.linspace(1,372,372) ax.plot(xtime, sp12, 'black', alpha=1.00, linewidth=2) ax.fill_between(xtime, 0., sp12, sp12> 0., color='blue', alpha=.75) ax.fill_between(xtime, 0., sp12, sp12< 0., color='red', alpha=.75) plt.xlabel('Years') plt.ylabel('SPI') plt.title('SPI-12 Macuelizo[ (1985-2015)', fontsize=12) ax.axhline(-0.6, color='red', label='SPI - 0.6') ax.axhline(-1.3, color='magenta', label='SPI - 1.3') ax.axvspan(1997, 1998, color='magenta', alpha=0.7) ax.set_xlim(0, 372) ax.set_ylim(-4, 3) ax.set_xticklabels(range(1985,2016,1*4)) plt.grid(True) plt.legend() ax.autoscale_view() plt.savefig('SP12_macuelizo.jpg')
根因分析
问题核心是传入axvspan的坐标和x轴实际数值范围完全不匹配:
- 代码中x轴实际取值是0~372,对应1985-2015年共372个月份的序列索引,本身不存在1997、1998这两个坐标点
axvspan(1997,1998)把高亮块画到了x轴1997~1998的位置,远超出set_xlim(0,372)设置的可视范围,matplotlib不会渲染可视区域外的元素,也不会抛出坐标越界的错误- 额外隐患:直接调用
set_xticklabels修改刻度标签但未设置对应刻度位置,会导致年份标签和实际x轴位置错位,就算高亮位置正确也会出现标签和区域对不齐的问题;末尾的autoscale_view()会自动调整坐标轴范围,容易把可视区域拉偏。
修复方案
- 先把需要高亮的年份转换成x轴对应的序列索引:x轴从1985年1月(x=1位置)开始计数,年份
y对应的x坐标为(y-1985)*12 - 用转换后的坐标替换axvspan中直接写的年份数值
- 先设置x轴刻度位置,再绑定年份标签,避免错位
- 移除多余的
autoscale_view()调用,防止坐标轴范围被自动修改
修正后代码
fig = plt.figure(figsize=(15, 6)) ax = fig.add_subplot(111) xtime = np.linspace(1,372,372) ax.plot(xtime, sp12, 'black', alpha=1.00, linewidth=2) ax.fill_between(xtime, 0., sp12, sp12> 0., color='blue', alpha=.75) ax.fill_between(xtime, 0., sp12, sp12< 0., color='red', alpha=.75) plt.xlabel('Years') plt.ylabel('SPI') plt.title('SPI-12 Macuelizo (1985-2015)', fontsize=12) ax.axhline(-0.6, color='red', label='SPI - 0.6') ax.axhline(-1.3, color='magenta', label='SPI - 1.3') # 转换高亮年份为x轴实际坐标 highlight_start = (1997 - 1985) * 12 highlight_end = (1998 - 1985) * 12 ax.axvspan(highlight_start, highlight_end, color='magenta', alpha=0.7, label='1997-1998') ax.set_xlim(0, 372) ax.set_ylim(-4, 3) # 先设置刻度位置再绑定标签,避免错位 tick_pos = [(y - 1985)*12 for y in range(1985,2016,4)] ax.set_xticks(tick_pos) ax.set_xticklabels(range(1985,2016,4)) plt.grid(True) plt.legend() plt.savefig('SP12_macuelizo.jpg', dpi=300, bbox_inches='tight')
内容的提问来源于stack exchange,提问作者Juan Carlos
相关产品推荐
相关产品推荐

