Place tick labels between ticks for time series charts

49 Views Asked by At

When plotting a time series, plotting software (like Matplotlib) generally puts the ticks at a specific instant in time. But I find labeling periods or spans of time to be a much more natural way to display time series data. I.e. daily stock prices throughout the month over October 2023.

With Matplotlib, I can set a minor tick label as say monthly, and a major tick as yearly, and then offset the tick labels so they appear in between the ticks. But the problem is the first minor tick label is missing. I believe this is by design (https://github.com/matplotlib/matplotlib/issues/13618/), but for my purposes I would like Matplotlib to not drop the first minor tick within the major tick. Is this possible?

And is there a better way to offset the labels than the transform I have below;

from datetime import date
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib as mpl

fig, ax = plt.subplots(figsize=(16,4))

# set plot date range
startdate = date(2023,1,1)
enddate = date(2025,7,1)
ax.set_xlim([startdate, enddate])

# set grid and x ticks
ax.grid(which='major', axis='x', color='b')
ax.tick_params(axis='x', which='major', length=16, width=1, colors='b')
ax.grid(which='minor', axis='x', color='y')
ax.tick_params(axis='x', which='minor', length=8, width=1, colors='y')

# Set major x ticks
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))

# offset major x tick labels
for label in ax.xaxis.get_majorticklabels():
    label.set_transform(mpl.transforms.Affine2D().translate(365/2, 0) +label.get_transform())

# Set minor x ticks
ax.xaxis.set_minor_locator(mdates.MonthLocator())
ax.xaxis.set_minor_formatter(mdates.DateFormatter('%b'))
# offset minor x tick labels
for label in ax.xaxis.get_minorticklabels():
    label.set_transform(mpl.transforms.Affine2D().translate(15, 0) +label.get_transform())
    
plt.setp(ax.get_xticklabels(which='minor')[-1], visible=False)

enter image description here

0

There are 0 best solutions below