Date ticks and rotation in matplotlib

匿名 (未验证) 提交于 2019-12-03 02:06:01

问题:

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() 

回答1:

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

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 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

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

after the two avail_plot calls. This sets the rotation on the correct axes specifically.



回答2:

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

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

The additional bottom argument is equivalent to setting plt.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.



回答3:

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 as 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 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 with plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )



回答4:

Another way to applyhorizontalalignment and rotation to each tick label is doing a for loop over the tick labels 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 np.arange(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") 

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 np.arange(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") 



回答5:

plt.imshow() method

import matplotlib.pyplot as plt import pandas as pd  corr = df.corr() plt.imshow (corr, cmap='Blues') plt.xticks(range(len(corr.columns)), corr.columns, rotation=35) plt.yticks(range(len(corr.columns)), corr.columns) plt.colorbar() plt.show() 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!