python - example - Las series de tiempos de las pandas trazan el ajuste del eje x y las marcas y etiquetas mayores y menores
plot kind='' bar (1)
Quiero ser capaz de establecer los xticks mayores y menores y sus etiquetas para un gráfico de series de tiempo trazadas a partir de un objeto de serie temporal de Pandas.
La página de Pandas 0.9 "lo nuevo" dice:
"puede usar to_pydatetime o registrar un convertidor para el tipo Timestamp"
pero no puedo encontrar la manera de hacerlo para poder usar los comandos ax.xaxis.set_major_locator
y ax.xaxis.set_major_formatter
(y minor).
Si los utilizo 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 tics principales a pandas.plot, y luego establecer las principales etiquetas tic. No puedo descifrar cómo hacer las marcas menores usando este enfoque. (Puedo establecer 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 resultado:
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 más 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.
Tanto pandas
como matplotlib.dates
usan matplotlib.units
para localizar los ticks.
Pero mientras matplotlib.dates
tiene formas convenientes de configurar los ticks manualmente, pandas parece tener el enfoque en el formateo automático hasta el momento (puede echar un vistazo al code para la conversión de fechas y el formato en pandas).
Por lo tanto, por el momento parece más razonable 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 localidad es alemana, por lo que el martes [Tue] se convierte en Dienstag [Di])