Tick โ€‹โ€‹date and rotation in matplotlib

I had a problem with my date captions being rotated in matplotlib. The following is a small sample program. If I try to rotate the tics at the end, the tics will not rotate. If I try to rotate ticks, as shown in the 'crashes' comments, then matplot lib will work.

This only happens if the x values โ€‹โ€‹are dates. If I replace the dates variable with the t variable when calling avail_plot , calling xticks(rotation=70) works 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() 
+115
python matplotlib
Jun 29 2018-12-12T00:
source share
4 answers

If you prefer a non-object oriented approach, move plt.xticks (rotation = 70) right before two calls to avail_plot, for example

 plt.xticks(rotation=70) avail_plot(axs[0], dates, s1, 'testing', 'green') avail_plot(axs[1], dates, s1, 'testing2', 'red') 

This sets the rotation property before setting labels. Since you have two axes, plt.xticks gets confused after you make two plots. The moment plt.xticks does nothing, plt.gca () does not give you the axes you want to change, and therefore plt.xticks, which acts on the current axes, will not work.

For an object oriented approach not using plt.xticks, you can use

 plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 ) 

after two calls avail_plot. This sets the rotation at the corresponding points.

+184
Jun 29 '12 at 21:40
source share

The solution works for matplotlib 2.1 +

There is a tick_params axis method that can change the properties of a tick. It also exists as an axis method like set_tick_params

 ax.tick_params(axis='x', rotation=45) 

Or

 ax.xaxis.set_tick_params(rotation=45) 

As a side note, the current solution mixes the state interface (using pyplot) with an object-oriented interface using the plt.xticks(rotation=70) . Since the code in the question uses an object-oriented approach, it is best to stick with this approach. The solution really gives a good explicit solution with plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )

+55
09 Oct '17 at 17:47 on
source share

A simple solution that avoids looping over ticklabes is to simply use

fig.autofmt_xdate()

This command automatically rotates the xaxis labels and adjusts their position. The default values โ€‹โ€‹are a rotation angle of 30 ยฐ and horizontal alignment "to the right." But they can be changed when the function is called.

 fig.autofmt_xdate(bottom=0.2, rotation=30, ha='right') 

The optional bottom argument is equivalent to setting plt.subplots_adjust(bottom=bottom) , which allows you to set the addition of the lower axes to a larger value to accommodate rotated labels.

So basically here you have all the settings you need in order to have a good date axis in one command.

A good example can be found on the matplotlib page.

+29
Mar 19 '17 at 15:25
source share

Another way to apply horizontalalignment and rotation to each tick mark is to make a for loop on the tick marks you want to change:

 import numpy as np import matplotlib.pyplot as plt import datetime as dt now = dt.datetime.now() hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)] days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)] hours_value = np.random.random(len(hours)) days_value = np.random.random(len(days)) fig, axs = plt.subplots(2) fig.subplots_adjust(hspace=0.75) axs[0].plot(hours,hours_value) axs[1].plot(days,days_value) for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels(): label.set_rotation(30) label.set_horizontalalignment("right") 

enter image description here

And here is an example if you want to control the location of major and minor ticks:

 import numpy as np import matplotlib.pyplot as plt import datetime as dt fig, axs = plt.subplots(2) fig.subplots_adjust(hspace=0.75) now = dt.datetime.now() hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)] days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)] axs[0].plot(hours,np.random.random(len(hours))) x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True) x_minor_lct = matplotlib.dates.HourLocator(byhour = range(0,25,1)) x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct) axs[0].xaxis.set_major_locator(x_major_lct) axs[0].xaxis.set_minor_locator(x_minor_lct) axs[0].xaxis.set_major_formatter(x_fmt) axs[0].set_xlabel("minor ticks set to every hour, major ticks start with 00:00") axs[1].plot(days,np.random.random(len(days))) x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True) x_minor_lct = matplotlib.dates.DayLocator(bymonthday = range(0,32,1)) x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct) axs[1].xaxis.set_major_locator(x_major_lct) axs[1].xaxis.set_minor_locator(x_minor_lct) axs[1].xaxis.set_major_formatter(x_fmt) axs[1].set_xlabel("minor ticks set to every day, major ticks show first day of month") for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels(): label.set_rotation(30) label.set_horizontalalignment("right") 

enter image description here

+9
Jan 26 '17 at 20:39 on
source share



All Articles