如何在matplotlib中调整柱状图层级日期X轴的两端对齐问题
问题描述
我的目标是创建带日期的层级X轴,参考相关方案完成实现后,线图场景下运行完全正常,将图表类型改为柱状图后,两个X轴的首尾刻度无法对齐,具体实现逻辑如下:
实现代码
首先是展示日信息的第一个X轴代码:
import pandas as pd import numpy as np from matplotlib import pyplot as plt import matplotlib.ticker as ticker date = ['2021-01-29', '2021-01-30', '2021-01-31', '2021-02-01', '2021-02-02', '2021-01-03', '2021-01-04'] day = ['29', '30', '31', '01', '02', '03', '04'] data = [5, 4, 3, 9, 7, 8, 2] fig = plt.figure(num="TEST") ax1 = fig.add_subplot(1, 1, 1) # 线图时用这行 # ax1.plot(date, data) # 柱状图时替换为这行 ax1.bar(date, data) ax1.set_xticks(date) ax1.set_xticklabels(day) ax1.margins(x=0)
其次是生成展示月份的第二个X轴代码:
ax2 = ax1.twiny() ax2.spines['bottom'].set_position(('axes', -0.08)) ax2.tick_params('both', direction='in', which='major') ax2.xaxis.set_ticks_position('bottom') ax2.xaxis.set_label_position('bottom') ax2.set_xticks([0, 2.5, 6]) ax2.xaxis.set_major_formatter(ticker.NullFormatter()) ax2.xaxis.set_minor_locator(ticker.FixedLocator([1, 4])) ax2.xaxis.set_minor_formatter(ticker.FixedFormatter(['JAN', 'FEB'])) plt.show()
问题原因
线图设置ax1.margins(x=0)后,X轴范围刚好为[0, 6](7个日期分类对应坐标0~6,无左右边距),和手动设置的ax2刻度位置匹配;但柱状图默认会给X轴左右各加0.5的边距,实际X轴范围变为[-0.5, 6.5],和硬编码的ax2刻度位置不匹配,就出现了偏移。
解决方案
可根据需求选择以下任意一种改法:
方案1:强制统一X轴范围,适配原有刻度逻辑
在绘制柱状图后,显式设置ax1的X轴范围和线图一致,原有ax2的刻度设置无需修改:
ax1.bar(date, data) ax1.set_xticks(date) ax1.set_xticklabels(day) ax1.margins(x=0) # 新增这行,强制X轴范围和线图一致 ax1.set_xlim(0, len(date)-1)
方案2:动态适配X轴范围,保留柱状图默认边距
如果不想修改柱状图默认的左右边距(避免边缘柱子被截断),可以先同步ax2和ax1的X轴范围,再调整ax2的刻度位置:
ax2 = ax1.twiny() # 新增这行,同步两个X轴的范围,保证首尾完全对齐 ax2.set_xlim(ax1.get_xlim()) ax2.spines['bottom'].set_position(('axes', -0.08)) ax2.tick_params('both', direction='in', which='major') ax2.xaxis.set_ticks_position('bottom') ax2.xaxis.set_label_position('bottom') # 修改刻度位置适配新的X轴范围 ax2.set_xticks([-0.5, 2.5, 6.5]) ax2.xaxis.set_major_formatter(ticker.NullFormatter()) ax2.xaxis.set_minor_locator(ticker.FixedLocator([1, 4])) ax2.xaxis.set_minor_formatter(ticker.FixedFormatter(['JAN', 'FEB']))
内容的提问来源于stack exchange,提问作者Ricardo Carrera
相关产品推荐
相关产品推荐

