I am having an issue trying to get my date ticks rotated in matplotlib. A small sample program is below. If I try to rotate the ticks at the end, the ticks do not get rotated. If I try to rotate the ticks as shown under the comment 'crashes', then matplot lib crashes.
This only happens if the x-values are dates. If I replaces the variable dates
with the variable t
in the call to avail_plot
, the xticks(rotation=70)
call works just fine inside avail_plot
.
Any ideas?
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
def avail_plot(ax, x, y, label, lcolor):
ax.plot(x,y,'b')
ax.set_ylabel(label, rotation='horizontal', color=lcolor)
ax.get_yaxis().set_ticks([])
#crashes
#plt.xticks(rotation=70)
ax2 = ax.twinx()
ax2.plot(x, [1 for a in y], 'b')
ax2.get_yaxis().set_ticks([])
ax2.set_ylabel('testing')
f, axs = plt.subplots(2, sharex=True, sharey=True)
t = np.arange(0.01, 5, 1)
s1 = np.exp(t)
start = dt.datetime.now()
dates=[]
for val in t:
next_val = start + dt.timedelta(0,val)
dates.append(next_val)
start = next_val
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
plt.subplots_adjust(hspace=0, bottom=0.3)
plt.yticks([0.5,],("",""))
#doesn't crash, but does not rotate the xticks
#plt.xticks(rotation=70)
plt.show()
If you prefer a non-object-oriented approach, move plt.xticks(rotation=70) to right before the two avail_plot calls, eg
This sets the rotation property before setting up the labels. Since you have two axes here, plt.xticks gets confused after you've made the two plots. At the point when plt.xticks doesn't do anything, plt.gca() does not give you the axes you want to modify, and so plt.xticks, which acts on the current axes, is not going to work.
For an object-oriented approach not using plt.xticks, you can use
after the two avail_plot calls. This sets the rotation on the correct axes specifically.
Another way to apply
horizontalalignment
androtation
to each tick label is doing afor
loop over the tick labels you want to change:And here is an example if you want to control the location of major and minor ticks:
Solution works for matplotlib 2.1+
There exists an axes method
tick_params
that can change tick properties. It also exists as an axis method asset_tick_params
Or
As a side note, the current solution mixes the stateful interface (using pyplot) with the object-oriented interface by using the command
plt.xticks(rotation=70)
. Since the code in the question uses the object-oriented approach, it's best to stick to that approach throughout. The solution does give a good explicit solution withplt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
An easy solution which avoids looping over the ticklabes is to just use
fig.autofmt_xdate()
This command automatically rotates the xaxis labels and adjusts their position. The default values are a rotation angle 30° and horizontal alignment "right". But they can be changed in the function call
The additional
bottom
argument is equivalent to settingplt.subplots_adjust(bottom=bottom)
, which allows to set the bottom axes padding to a larger value to host the rotated ticklabels.So basically here you have all the settings you need to have a nice date axis in a single command.
A good example can be found on the matplotlib page.