1

Problem: I am trying to make a very simple bar chart in Matplotlib of a Pandas DataFrame. The DateTime index is causing confusion, however: Matplotlib does not appear to understand the Pandas DateTime, and is labeling the years incorrectly. How can I fix this?

Code

# Make date time series
index_dates = pd.date_range('2018-01-01', '2021-01-01')

# Make data frame with some random data, using the date time index
df = pd.DataFrame(index=index_dates,
                  data = np.random.rand(len(index_dates)), 
                  columns=['Data'])

# Make a bar chart in marplot lib
fig, ax = plt.subplots(figsize=(12,8))

df.plot.bar(ax=ax)

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

Instead of showing up as 2018-2021, however, the years show up as 1970 - 1973. enter image description here

I've already looked at the answers here, here, and documentation here. I know the date timeindex is in fact a datetime index because when I call df.info() it shows it as a datetime index, and when I call index_dates[0].year it returns 2018. How can I fix this? Thank you!

BLimitless
  • 2,060
  • 5
  • 17
  • 32

1 Answers1

1

The problem is with mixing df.plot.bar and matplotlib here.

df.plot.bar sets tick locations starting from 0 (and assigns labels), while matplotlib.dates expects the locations to be the number of days since 1970-01-01 (more info here).

If you do it with matplotlib directly, it shows labels correctly:

# Make a bar chart in marplot lib
fig, ax = plt.subplots(figsize=(12,8))

plt.bar(x=df.index, height=df['Data'])

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

Output:

chart

perl
  • 9,826
  • 1
  • 10
  • 22
  • 1
    Thank you for the answer, this worked great! Changed from plt.bar() to ax.bar() to keep track of axis object more carefully. – BLimitless Mar 17 '21 at 23:41