J'ai un problème à essayer de faire pivoter mes ticks de date dans matplotlib. Un petit exemple de programme est ci-dessous. Si j'essaie de faire pivoter les ticks à la fin, les ticks ne sont pas soumis à une rotation. Si j'essaie de faire pivoter les ticks, comme indiqué dans le commentaire "Crashes", alors lib lib de Matplot se bloque.
Cela ne se produit que si les valeurs x sont des dates. Si je remplace la variable dates
par la variable t
dans l'appel à avail_plot
, l'appel xticks(rotation=70)
fonctionne parfaitement à l'intérieur de avail_plot
.
Des idées?
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()
Si vous préférez une approche non orientée objet, déplacez plt.xticks (rotation = 70) vers la droite avant les deux appels de avail_plot, par exemple
plt.xticks(rotation=70)
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
Ceci définit la propriété rotation avant de configurer les étiquettes. Puisque vous avez deux axes ici, plt.xticks devient confus une fois que vous avez créé les deux parcelles. Au moment où plt.xticks ne fait rien, plt.gca () fait not vous donne les axes que vous souhaitez modifier, et ainsi plt.xticks, qui agit sur les axes actuels, est ne va pas au travail.
Pour une approche orientée objet qui n’utilise pas plt.xticks, vous pouvez utiliser
plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
after les deux appels de avail_plot. Ceci définit spécifiquement la rotation sur les bons axes.
La solution fonctionne pour matplotlib 2.1 +
Il existe une méthode d'axes tick_params
pouvant modifier les propriétés des ticks. Il existe également en tant que méthode d'axe comme set_tick_params
ax.tick_params(axis='x', rotation=45)
Ou
ax.xaxis.set_tick_params(rotation=45)
En guise de remarque, la solution actuelle mélange l'interface à états (avec pyplot) à l'interface orientée objet à l'aide de la commande plt.xticks(rotation=70)
. Comme le code de la question utilise l'approche orientée objet, il est préférable de s'en tenir à cette approche. La solution donne une bonne solution explicite avec plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
Une solution simple qui évite de passer en boucle sur les ticklabes consiste simplement à utiliser
Cette commande fait automatiquement pivoter les étiquettes xaxis et ajuste leur position. Les valeurs par défaut sont un angle de rotation de 30 ° et un alignement horizontal "à droite". Mais ils peuvent être modifiés dans l'appel de fonction
fig.autofmt_xdate(bottom=0.2, rotation=30, ha='right')
L'argument additionnel bottom
équivaut à la définition de plt.subplots_adjust(bottom=bottom)
, qui permet de définir une valeur plus grande pour le remplissage des axes inférieurs afin d'héberger les étiquettes croisées pivotées.
En gros, vous avez ici tous les paramètres nécessaires pour avoir un axe de date Nice en une seule commande.
Un bon exemple peut être trouvé sur la page matplotlib.
Une autre façon d'appliquerhorizontalalignment
et rotation
à chaque étiquette de tick est de faire une boucle for
sur les étiquettes de tick que vous souhaitez modifier:
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")
Et voici un exemple si vous souhaitez contrôler l'emplacement des ticks majeurs et mineurs:
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")