可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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()