1

I am trying to draw a simple chart with matplotlib. I've got numbers on the vertical axis, and dates on the horizontal axis. For some reason I can't figure out, the 2nd x-axis tick label refuses to rotate. The remaining tick labels are rotated just fine. If I change my data, the same thing happens...it's always the 2nd tick label that refuses to rotate. I'm at my wits' end. Here's my code:

import datetime
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
from matplotlib.dates import MonthLocator, DateFormatter
import matplotlib.ticker as ticker

plt.rcdefaults()
fig, ax = plt.subplots()
fig.set_size_inches(6.5, 3)

# Example data
values = [ 270, 318, 349, 322, 433, 444, 459, 481, 449, 558, 575, 843]
dlist = [ datetime.datetime(2020,10,1), datetime.datetime(2020,11,1), datetime.datetime(2020,12,1), datetime.datetime(2021,1,1), datetime.datetime(2021,2,1), datetime.datetime(2021,3,1), datetime.datetime(2021,4,1), datetime.datetime(2021,5,1), datetime.datetime(2021,6,1), datetime.datetime(2021,7,1), datetime.datetime(2021,8,1), datetime.datetime(2021,9,1)]
ax.set_box_aspect(.25)
ax.xaxis.set_major_locator(MonthLocator(interval=1))
ax.xaxis.set_major_formatter(DateFormatter('%b %Y'))
ax.yaxis.set_major_locator(ticker.FixedLocator([0, 200, 400, 600, 800, 1000]))

plt.setp(ax.get_xticklabels(), fontsize=8, rotation=45, ha='right')
plt.setp(ax.get_yticklabels(), fontsize=8)
ax.set_ylabel('Attack Volume', fontsize=10)

ax.set_xlim(dlist[0], dlist[-1])
ax.set_ylim(0,1000)
ax.grid(True)

ax.set_title('Figure 1: Attack Volume Trend', fontsize=12)
ax.plot(dlist, values, 'o-')
plt.show()

And here is what I see:

Plot output as it appears on my screen

Sorry about the link instead of an embedded image - I am a new StackOverflow user so they will not let me embed anything yet. What am I doing wrong?

I'm using matplotlib-3.4.3 on MacOS Big Sur 11.5.2 (20G95).

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158

1 Answers1

3

Ok, I figured it out. I needed to call

plt.setp(ax.get_xticklabels(), fontsize=8, rotation=45, ha='right')
plt.setp(ax.get_yticklabels(), fontsize=8)
ax.set_ylabel('Attack Volume', fontsize=10)

before I called

ax.xaxis.set_major_locator(MonthLocator(interval=1))
ax.xaxis.set_major_formatter(DateFormatter('%b %Y'))
ax.yaxis.set_major_locator(ticker.FixedLocator([0, 200, 400, 600, 800, 1000]))

So the following code works:

#!/usr/bin/env python3
import datetime
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
from matplotlib.dates import MonthLocator, DateFormatter
import matplotlib.ticker as ticker

plt.rcdefaults()
fig, ax = plt.subplots()
fig.set_size_inches(6.5, 3)

# Example data
values = [ 270, 318, 349, 322, 433, 444, 459, 481, 449, 558, 575, 843]
dlist = [ datetime.datetime(2020,10,1), datetime.datetime(2020,11,1), datetime.datetime(2020,12,1), datetime.datetime(2021,1,1), datetime.datetime(2021,2,1), datetime.datetime(2021,3,1), datetime.datetime(2021,4,1), datetime.datetime(2021,5,1), datetime.datetime(2021,6,1), datetime.datetime(2021,7,1), datetime.datetime(2021,8,1), datetime.datetime(2021,9,1)]

plt.setp(ax.get_xticklabels(), fontsize=8, rotation=45, ha='right')
plt.setp(ax.get_yticklabels(), fontsize=8)
ax.set_ylabel('Attack Volume', fontsize=10)

ax.set_box_aspect(.25)
ax.xaxis.set_major_locator(MonthLocator(interval=1))
ax.xaxis.set_major_formatter(DateFormatter('%b %Y'))
ax.yaxis.set_major_locator(ticker.FixedLocator([0, 200, 400, 600, 800, 1000]))

ax.set_xlim(dlist[0], dlist[-1])
ax.set_ylim(0,1000)
ax.grid(True)

ax.set_title('Figure 1: Attack Volume Trend', fontsize=12)
ax.plot(dlist, values, 'o-')
plt.show()