Using DateFormatter resets starting date to 1970

I have a dataframe where the index is the first date of each month and the size column is the frequency for that month, e.g.

a table showing a list of 1st of the month dates and a frequency

Using .index on the dataframe confirms the type of the index is DatetimeIndex:

DatetimeIndex(['2006-12-01', ...],
              dtype='datetime64[ns]', name='created_at_month', length=175, freq=None)

Using .plot() on the DataFrame I can produce a line graph per month:

enter image description here

However, it only lists every other year on the x axis, and I’d like it to list each year on the axis.

I would expect to be able to do

ax.xaxis.set_major_locator(mdates.YearLocator(1))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))

However this doesn’t output any labels at all.

If I add a minor formatter (ax.xaxis.set_minor_formatter(mdates.DateFormatter('%d %m %Y'))), I get this:

enter image description here

What am I doing wrong here to cause the dates to change?

The relevant versions are:

  • Matplotlib: 3.3.4
  • Pandas: 1.2.4
  • Python: 3.8.8

Answer

As reported here, for some reason pandas‘s plot shows this issue.
You can overcome this issue by replacing pandas‘ plot with matplotlib.pyplot.plot.
You can take this answer as a reference for 2 datetime ticks on x axis (month and year, or month and day, or day and hour, as you need), using two different axis in palce of minor and major ticks.

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


df = pd.DataFrame({'created_at_month': pd.date_range(start = '2006-12-01', end = '2020-12-01', freq = 'MS')})
df['size'] = np.random.randint(0, 200, len(df))
df = df.set_index('created_at_month')


fig, ax = plt.subplots()

ax.plot(df.index, df['size'])

ax.xaxis.set_major_locator(mdates.YearLocator(base = 1, month = 1, day = 1))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))

plt.show()

enter image description here