Search code examples
pythonpandasmatplotlibdate-rangexticks

Matplotlib major and minor ticks misaligned when using pandas date_range


I am trying to use pandas date_range in the x-axis of a matplotlib.pyplot graph, while setting years to be the major ticks and months to be the minor ticks (for a timeline plot).

I came across a seemingly unexpected behaviour (noticed also as part of this SO question but unsolved), where the ticks are not aligned, and they are exhibiting an offset.

This code reproduces it for me (v3.5.2):

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib.dates as mdates

x_range = pd.date_range('2015-01-01', '2021-06-01', freq='m')
y = np.linspace(1,1, len(x_range))

fig, ax = plt.subplots(figsize=(10, 1))
ax.plot(x_range, y)

loc = mdates.MonthLocator(interval=12)
ax.xaxis.set_major_locator(loc)
ax.xaxis.set_minor_locator(AutoMinorLocator(12))

fmt = mdates.DateFormatter('%Y')
ax.xaxis.set_major_formatter(fmt)

enter image description here

Anyone dealt with this before? I suspect it has to do with months having 28, 30 and 31 days but could not investigate further.


Solution

  • You could do the following:

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import matplotlib.dates as mdates
    
    x_range = pd.date_range('2015-01-01', '2021-06-01', freq='A')
    y = np.linspace(1, 1, len(x_range))
    
    fig, ax = plt.subplots(figsize=(10, 1))
    ax.plot(x_range, y)
    
    loc = mdates.YearLocator()
    ax.xaxis.set_major_locator(loc)
    ax.xaxis.set_minor_locator(mdates.MonthLocator())
    
    fmt = mdates.DateFormatter('%Y')
    ax.xaxis.set_major_formatter(fmt)
    
    plt.show()
    

    enter image description here