My goal is to create a hierarchical x-axis with the dates. To do this, I am following the steps of this
However, when I change the chart type to bar ax1.bar(date, data)
, the beginning and end ticks of both axis don't match :
Is there a way for both axis to start and end at the same point? Either extending the first axis all the way (regardless overlapping) or adjusting the second axis to match the first axis.
CodePudding user response:
To get both x-axis nicely aligned, it is important that they have the same datalimits (ax2.set_xlim(ax1.get_xlim())
). Then, ax2.set_xticks([0, 2.5, 6])
will have the ticks at the center of the first and last bar, and inbetween the third and fourth.
You can use ax2.spines['bottom'].set_bounds([0, 6])
to stop the x-axis at those positions.
If you also want to hide the tick marks of ax1
, the standard way is to set their length to zero: ax1.tick_params(axis='x', length=0)
.
If desired, you can also hide the top and right spines. You'll need to do that for both axes.
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, ax1 = plt.subplots(num="TEST")
ax1.bar(date, data)
ax1.set_xticks(np.arange(len(date)))
ax1.set_xticklabels(day)
ax1.margins(x=0)
ax1.tick_params(axis='x', length=0) # hide tick marks
ax2 = ax1.twiny()
ax2.spines['bottom'].set_position(('axes', -0.08))
ax2.tick_params(axis='x', direction='in', which='major')
ax2.xaxis.set_ticks_position('bottom')
ax2.xaxis.set_label_position('bottom')
ax2.set_xlim(ax1.get_xlim()) # same datalimits
ax2.set_xticks([0, 2.5, 6])
ax2.spines['bottom'].set_bounds([0, 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']))
for ax in (ax1, ax2):
for spine in ['top', 'right']:
ax.spines[spine].set_visible(False)
plt.tight_layout()
plt.show()
Instead of shorten, set_bounds()
can also extend a bit. For example:
ax2.set_xticks([-0.5, 2.5, 6.5])
ax2.spines['bottom'].set_bounds([-0.5, 6.5])