Neal
Tengo un problema al tratar de rotar mis marcas de fecha en matplotlib. A continuación se muestra un pequeño programa de muestra. Si trato de rotar las marcas al final, las marcas no se rotan. Si trato de rotar las marcas como se muestra debajo del comentario ‘falla’, entonces matplot lib falla.
Esto solo sucede si los valores de x son fechas. Si reemplazo la variable dates
con la variable t
en la llamada a avail_plot
el xticks(rotation=70)
la llamada funciona bien por dentro avail_plot
.
¿Algunas 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
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()
cge
Si prefiere un enfoque no orientado a objetos, muévase plt.xticks(rotation=70)
a derecha antes los dos avail_plot
llamadas, por ejemplo
plt.xticks(rotation=70)
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
Esto establece la propiedad de rotación antes de configurar las etiquetas. Ya que tienes dos hachas aquí, plt.xticks
se confunde después de haber hecho las dos tramas. en el momento en que plt.xticks
no hace nada, plt.gca()
hace no darle los ejes que desea modificar, y así plt.xticks
que actúa sobre los ejes actuales, no va a funcionar.
Para un enfoque orientado a objetos que no utilice plt.xticks
puedes usar
plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
después los dos avail_plot
llamadas Esto establece la rotación en los ejes correctos específicamente.
-
Otra cosa útil: cuando llamas
plt.setp
puede establecer varios parámetros especificándolos como argumentos de palabras clave adicionales. elhorizontalalignment
kwarg es particularmente útil cuando gira las etiquetas de marca:plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70, horizontalalignment='right' )
– 8uno6
4 de agosto de 2015 a las 12:54
-
No me gusta esta solución ya que mezcla los enfoques de pyplot y orientado a objetos. solo puedes llamar
ax.tick_params(axis='x', rotation=70)
en cualquier lugar–Ted Petrou
9 oct 2017 a las 17:41
-
@TedPetrou ¿Qué quiere decir con “mezclar” aquí? el
plt.setp
La solución está completamente orientada a objetos. Si no le gusta el hecho de que hay algunosplt
en ella, utilizafrom matplotlib.artist import setp; setp(ax.get_xticklabels(), rotation=90)
en cambio.– La Importancia De Ser Ernesto
9 oct 2017 a las 19:29
-
@ImportanceOfBeingErnest La primera línea de código utiliza
plt.xticks
que es pyplot. La documentación en sí dice que no se mezclen estilos.plt.setp
es más detallado pero tampoco tiene el típico estilo orientado a objetos. Tu respuesta es definitivamente la mejor aquí. Básicamente, cualquier cosa con una función no está orientada a objetos. No importa si importassetp
O no.–Ted Petrou
9 oct 2017 a las 19:37
-
Gran parte del código de la pregunta usa pyplot, como
yticks
y el código no tiene ax definido en absoluto fuera deavail_plot
…– cge
9 oct 2017 a las 19:43
Ted Petrou
La solución funciona para matplotlib 2.1+
Existe un método de ejes. tick_params
que puede cambiar las propiedades de las marcas. También existe como un método de eje como set_tick_params
ax.tick_params(axis="x", rotation=45)
O
ax.xaxis.set_tick_params(rotation=45)
Como nota al margen, la solución actual combina la interfaz con estado (usando pyplot) con la interfaz orientada a objetos usando el comando plt.xticks(rotation=70)
. Dado que el código de la pregunta utiliza el enfoque orientado a objetos, es mejor ceñirse a ese enfoque en todo momento. La solución da una buena solución explícita con plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )
-
¿Es posible cambiar la rotación predeterminada para todas las parcelas? Creo que necesito cambiar esto en cada parcela que hago.
– Chogg
17 de junio de 2020 a las 18:48
-
Parece el método más OOP aquí.
– minutos
9 de noviembre de 2020 a las 16:26
La Importancia De SerErnest
Una solución fácil que evita pasar por encima de los ticklabes es simplemente usar
Este comando gira automáticamente las etiquetas del eje x y ajusta su posición. Los valores predeterminados son un ángulo de rotación de 30° y una alineación horizontal “derecha”. Pero se pueden cambiar en la llamada de función.
fig.autofmt_xdate(bottom=0.2, rotation=30, ha="right")
El adicional bottom
argumento es equivalente a establecer plt.subplots_adjust(bottom=bottom)
que permite establecer el relleno de los ejes inferiores en un valor mayor para alojar las etiquetas rotadas.
Básicamente, aquí tiene todas las configuraciones que necesita para tener un buen eje de fecha en un solo comando.
A buen ejemplo se puede encontrar en la página de matplotlib.
-
¡Gran respuesta! ¡Gracias!
– Abramodj
7 julio 2017 a las 11:25
-
¿Puedes controlar el parámetro ‘modo_rotación’ a través de esta función?
– TeoríaX
24 de febrero de 2020 a las 14:54
-
@TheoryX No. Si necesita el modo de rotación, debe usar el
plt.setp
enfoque, o bucle sobre las marcas (que es esencialmente lo mismo).– La Importancia De Ser Ernesto
24 de febrero de 2020 a las 14:57
-
Sí, es una solución fácil solo cuando el eje x está presente en la parte inferior del gráfico. Sin embargo, cuando el eje x está en la parte superior del gráfico o cuando dos ejes x (
twinx
) están presentes, estropea la alineación entre las marcas y las etiquetas de las marcas. En ese caso, la solución de Ted Petrou es mejor.– Ombrófilo
15 mayo 2020 a las 16:43
-
@Śubham Correcto. Esto es principalmente un atajo a todas las demás soluciones para el caso más común.
– La Importancia De Ser Ernesto
15 mayo 2020 a las 18:32
pablo reyes
Otra forma de aplicarhorizontalalignment
y rotation
a cada etiqueta de marca está haciendo un for
Recorra las etiquetas de marca que desea cambiar:
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")
Y aquí hay un ejemplo si desea controlar la ubicación de los ticks mayores y menores:
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")
Claramente llegué tarde, pero hay un ejemplo oficial que usa
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")
para rotar las etiquetas manteniéndolas correctamente alineadas con las marcas, lo cual es limpio y fácil.
Árbitro: https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html
molleja
Simplemente use
ax.set_xticklabels(label_list, rotation=45)
Crear un gráfico con fechas en el eje x es una tarea muy común; es una pena que no haya ejemplos más completos.
– alexw
13/03/2016 a las 20:29