xtick - plot python 3
Matplotlib que muestra las etiquetas x-tick superpuestas a pesar de los mejores esfuerzos (2)
Debido a la forma en que se maneja la representación del texto en matplotlib, la detección automática de texto superpuesto realmente ralentiza las cosas. (El espacio que ocupa el texto no puede calcularse con precisión hasta que se haya dibujado). Por esa razón, matplotlib no intenta hacerlo automáticamente.
Por lo tanto, es mejor rotar las etiquetas largas. Debido a que las fechas suelen tener este problema, hay un método de figura fig.autofmt_xdate()
que (entre otras cosas) rotará las etiquetas de tic para que sean un poco más legibles. (Nota: si está utilizando un método de plot
pandas, devuelve un objeto de ejes, por lo que deberá usar ax.figure.autofmt_xdate()
.
Como un ejemplo rápido:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
time = pd.date_range(''01/01/2014'', ''4/01/2014'', freq=''H'')
values = np.random.normal(0, 1, time.size).cumsum()
fig, ax = plt.subplots()
ax.plot_date(time, values, marker='''', linestyle=''-'')
fig.autofmt_xdate()
plt.show()
Si tuviéramos que dejar fig.autofmt_xdate()
out:
Y si usamos fig.autofmt_xdate()
:
Echa un vistazo a la gráfica de abajo:
Es un argumento secundario de esta figura más grande:
Veo dos problemas con ello. Primero, las etiquetas del eje x se superponen unas con otras (este es mi principal problema). Segundo. la ubicación de las líneas de cuadrícula menores del eje x parece un poco torpe. A la izquierda del gráfico, se ven correctamente espaciados. Pero a la derecha, parecen estar atestando las principales líneas de cuadrícula ... como si las principales ubicaciones de la línea de cuadrícula no fueran múltiplos adecuados de las ubicaciones menores de tick.
Mi configuración es que tengo un DataFrame llamado df
que tiene un Indice de fecha y hora en las filas y una columna llamada value
que contiene flotantes. Puedo proporcionar un ejemplo de los contenidos df
en un gist si es necesario. Una docena o más de líneas de df
están al final de esta publicación para referencia.
Aquí está el código que produce la figura:
now = dt.datetime.now()
fig, axes = plt.subplots(2, 2, figsize=(15, 8), dpi=200)
for i, d in enumerate([360, 30, 7, 1]):
ax = axes.flatten()[i]
earlycut = now - relativedelta(days=d)
data = df.loc[df.index>=earlycut, :]
ax.plot(data.index, data[''value''])
ax.xaxis_date()
ax.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
ax.get_yaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
ax.grid(b=True, which=''major'', color=''w'', linewidth=1.5)
ax.grid(b=True, which=''minor'', color=''w'', linewidth=0.75)
¿Cuál es mi mejor opción aquí para que las etiquetas del eje x dejen de superponerse entre sí (en cada una de las cuatro subparcelas)? Además, por separado (pero con menos urgencia), ¿qué pasa con el problema de la marca menor en la subparcela superior izquierda?
Estoy en Pandas 0.13.1, numpy 1.8.0 y matplotlib 1.4.x.
Aquí hay un pequeño fragmento de df
para referencia:
id scale tempseries_id value
timestamp
2014-11-02 14:45:10.302204+00:00 7564 F 1 68.0000
2014-11-02 14:25:13.532391+00:00 7563 F 1 68.5616
2014-11-02 14:15:12.102229+00:00 7562 F 1 68.9000
2014-11-02 14:05:13.252371+00:00 7561 F 1 69.0116
2014-11-02 13:55:11.792191+00:00 7560 F 1 68.7866
2014-11-02 13:45:10.782227+00:00 7559 F 1 68.6750
2014-11-02 13:35:10.972248+00:00 7558 F 1 68.4500
2014-11-02 13:25:10.362213+00:00 7557 F 1 68.1116
2014-11-02 13:15:10.822247+00:00 7556 F 1 68.2250
2014-11-02 13:05:10.102200+00:00 7555 F 1 68.5616
2014-11-02 12:55:10.292217+00:00 7554 F 1 69.0116
2014-11-02 12:45:10.382226+00:00 7553 F 1 69.3500
2014-11-02 12:35:10.642245+00:00 7552 F 1 69.2366
2014-11-02 12:25:12.642255+00:00 7551 F 1 69.1250
2014-11-02 12:15:11.122382+00:00 7550 F 1 68.7866
2014-11-02 12:05:11.332224+00:00 7549 F 1 68.5616
2014-11-02 11:55:11.662311+00:00 7548 F 1 68.2250
2014-11-02 11:45:11.122193+00:00 7547 F 1 68.4500
2014-11-02 11:35:11.162271+00:00 7546 F 1 68.7866
2014-11-02 11:25:12.102211+00:00 7545 F 1 69.2366
2014-11-02 11:15:10.422226+00:00 7544 F 1 69.4616
2014-11-02 11:05:11.412216+00:00 7543 F 1 69.3500
2014-11-02 10:55:10.772212+00:00 7542 F 1 69.1250
2014-11-02 10:45:11.332220+00:00 7541 F 1 68.7866
2014-11-02 10:35:11.332232+00:00 7540 F 1 68.5616
2014-11-02 10:25:11.202411+00:00 7539 F 1 68.2250
2014-11-02 10:15:11.932326+00:00 7538 F 1 68.5616
2014-11-02 10:05:10.922229+00:00 7537 F 1 68.9000
2014-11-02 09:55:11.602357+00:00 7536 F 1 69.3500
Edit: Trying fig.autofmt_xdate()
: No creo que esto vaya a hacer el truco. Esto parece utilizar las mismas etiquetas de marca x para ambos gráficos de la izquierda y también para los dos gráficos de la derecha. Lo cual no es correcto dados mis datos. Por favor vea la salida problemática a continuación:
Ok, finalmente lo tengo funcionando. El truco fue usar plt.setp
para rotar manualmente las etiquetas de tick. El uso de fig.autofmt_xdate()
no funcionó, ya que hace algunas cosas inesperadas cuando tienes varias subparcelas en tu figura. Aquí está el código de trabajo con su salida:
for i, d in enumerate([360, 30, 7, 1]):
ax = axes.flatten()[i]
earlycut = now - relativedelta(days=d)
data = df.loc[df.index>=earlycut, :]
ax.plot(data.index, data[''value''])
ax.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
ax.get_yaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
ax.grid(b=True, which=''major'', color=''w'', linewidth=1.5)
ax.grid(b=True, which=''minor'', color=''w'', linewidth=0.75)
plt.setp(ax.get_xticklabels(), rotation=30, horizontalalignment=''right'')
fig.tight_layout()
Por cierto, el comentario anterior sobre algunas cosas de matplotlib que tardan una eternidad es muy interesante aquí. Estoy usando una pi de frambuesa para actuar como una estación meteorológica en una ubicación remota. Es recoger los datos y servir los resultados a través de la web. Y chico, oh chico, es realmente sibilancias tratar de poner estos gráficos.