Quiero poder establecer los xticks mayores y menores y sus etiquetas para un gráfico de serie de tiempo trazada a partir de un objeto de serie de tiempo de Pandas.
La página de "novedades" de Pandas 0.9 dice:
"puede usar to_pydatetime o registrar un convertidor para el tipo de marca de tiempo"
pero no puedo averiguar cómo hacerlo para poder usar los comandos matplotlib ax.xaxis.set_major_locator
y ax.xaxis.set_major_formatter
(y menores).
Si los uso sin convertir los tiempos de los pandas, las marcas y etiquetas del eje x terminan mal.
Al usar el parámetro 'xticks', puedo pasar los ticks principales a pandas.plot y luego establecer las etiquetas de ticks principales. No puedo averiguar cómo hacer los ticks menores usando este enfoque. (Puedo configurar las etiquetas en los ticks menores predeterminados establecidos por pandas.plot)
Aquí está mi código de prueba:
import pandas
print 'pandas.__version__ is ', pandas.__version__
print 'matplotlib.__version__ is ', matplotlib.__version__
dStart = datetime.datetime(2011,5,1) # 1 May
dEnd = datetime.datetime(2011,7,1) # 1 July
dateIndex = pandas.date_range(start=dStart, end=dEnd, freq='D')
print "1 May to 1 July 2011", dateIndex
testSeries = pandas.Series(data=np.random.randn(len(dateIndex)),
index=dateIndex)
ax = plt.figure(figsize=(7,4), dpi=300).add_subplot(111)
testSeries.plot(ax=ax, style='v-', label='first line')
# using MatPlotLib date time locators and formatters doesn't work with new
# pandas datetime index
ax.xaxis.set_minor_locator(matplotlib.dates.WeekdayLocator(byweekday=(1),
interval=1))
ax.xaxis.set_minor_formatter(matplotlib.dates.DateFormatter('%d\n%a'))
ax.xaxis.grid(True, which="minor")
ax.xaxis.grid(False, which="major")
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('\n\n\n%b%Y'))
plt.show()
# set the major xticks and labels through pandas
ax2 = plt.figure(figsize=(7,4), dpi=300).add_subplot(111)
xticks = pandas.date_range(start=dStart, end=dEnd, freq='W-Tue')
print "xticks: ", xticks
testSeries.plot(ax=ax2, style='-v', label='second line',
xticks=xticks.to_pydatetime())
ax2.set_xticklabels([x.strftime('%a\n%d\n%h\n%Y') for x in xticks]);
# set the text of the first few minor ticks created by pandas.plot
# ax2.set_xticklabels(['a','b','c','d','e'], minor=True)
# remove the minor xtick labels set by pandas.plot
ax2.set_xticklabels([], minor=True)
# turn the minor ticks created by pandas.plot off
# plt.minorticks_off()
plt.show()
print testSeries['6/4/2011':'6/7/2011']
y su salida:
pandas.__version__ is 0.9.1.dev-3de54ae
matplotlib.__version__ is 1.1.1
1 May to 1 July 2011 <class 'pandas.tseries.index.DatetimeIndex'>
[2011-05-01 00:00:00, ..., 2011-07-01 00:00:00]
Length: 62, Freq: D, Timezone: None
xticks: <class 'pandas.tseries.index.DatetimeIndex'>
[2011-05-03 00:00:00, ..., 2011-06-28 00:00:00]
Length: 9, Freq: W-TUE, Timezone: None
2011-06-04 -0.199393
2011-06-05 -0.043118
2011-06-06 0.477771
2011-06-07 -0.033207
Freq: D
Actualización: he podido acercarme al diseño que quería usando un bucle para construir las principales etiquetas xtick:
# only show month for first label in month
month = dStart.month - 1
xticklabels = []
for x in xticks:
if month != x.month :
xticklabels.append(x.strftime('%d\n%a\n%h'))
month = x.month
else:
xticklabels.append(x.strftime('%d\n%a'))
Sin embargo, esto es un poco como hacer el eje x usando ax.annotate
: posible pero no ideal.
fuente
plot
función pandas y establecer todos los ticks después del trazado, utilizando métodos matplotlib delax
objeto devuelto (por ejemplo,ax.set_xticks
)?Respuestas:
Ambos
pandas
ymatplotlib.dates
usomatplotlib.units
para localizar las garrapatas.Pero si
matplotlib.dates
bien tiene formas convenientes de configurar los ticks manualmente, los pandas parecen estar enfocados en el formateo automático hasta ahora (puede ver el código para la conversión de fechas y el formato en pandas).Entonces, por el momento, parece más razonable de usar
matplotlib.dates
(como lo menciona @BrenBarn en su comentario).import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as dates idx = pd.date_range('2011-05-01', '2011-07-01') s = pd.Series(np.random.randn(len(idx)), index=idx) fig, ax = plt.subplots() ax.plot_date(idx.to_pydatetime(), s, 'v-') ax.xaxis.set_minor_locator(dates.WeekdayLocator(byweekday=(1), interval=1)) ax.xaxis.set_minor_formatter(dates.DateFormatter('%d\n%a')) ax.xaxis.grid(True, which="minor") ax.yaxis.grid() ax.xaxis.set_major_locator(dates.MonthLocator()) ax.xaxis.set_major_formatter(dates.DateFormatter('\n\n\n%b\n%Y')) plt.tight_layout() plt.show()
(mi configuración regional es alemana, por lo que el martes [mar] se convierte en Dienstag [Di])
fuente