Je veux pouvoir définir les xticks majeurs et mineurs et leurs étiquettes pour un graphe de série chronologique tracé à partir d'un objet de série temporelle Pandas.
La page Pandas 0.9 "quoi de neuf" dit:
"vous pouvez utiliser to_pydatetime ou enregistrer un convertisseur pour le type d'horodatage"
mais je ne peux pas comprendre comment faire cela pour pouvoir utiliser le matplotlib ax.xaxis.set_major_locator
et ax.xaxis.set_major_formatter
(et mineur) commandes.
Si je les utilise sans convertir les pandas fois), les graduations et les libellés de l'axe des x sont erronés.
En utilisant le paramètre 'xticks', je peux transmettre les repères principaux à pandas.plot, puis définir les libellés des repères principaux. Je ne peux pas comprendre comment faire les tics mineurs en utilisant cette approche. (Je peux définir les étiquettes sur les ticks mineurs par défaut définis par pandas.plot)
Voici mon code de test:
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']
et sa sortie:
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
Mise à jour: J'ai été en mesure de me rapprocher de la mise en page souhaitée en utilisant une boucle pour créer les principales étiquettes d'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'))
Cependant, c'est un peu comme si on faisait l'axe des x en utilisant ax.annotate
: possible mais pas idéal.
pandas
et matplotlib.dates
utilisation matplotlib.units
pour localiser les tiques.
Mais en même temps matplotlib.dates
dispose de moyens pratiques pour définir les graduations manuellement, pandas semble avoir jusqu’à présent mis l’accent sur le formatage automatique (vous pouvez consulter le code pour la conversion de date et mise en forme dans les pandas).
Donc, pour le moment, il semble plus raisonnable d'utiliser matplotlib.dates
(mentionné par @BrenBarn dans son commentaire).
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()
(ma langue est l'allemand, de sorte que mardi [mardi] devienne Dienstag [di])