Je veux pouvoir définir les xticks majeurs et mineurs et leurs étiquettes pour un graphique de série chronologique tracé à partir d'un objet de série chronologique Pandas.
La page "Quoi de neuf" de Pandas 0.9 indique:
"vous pouvez utiliser to_pydatetime ou enregistrer un convertisseur pour le type Timestamp"
mais je ne peux pas trouver comment faire cela pour pouvoir utiliser les commandes matplotlib ax.xaxis.set_major_locator
et ax.xaxis.set_major_formatter
(et mineures).
Si je les utilise sans convertir les temps des pandas, les graduations et les étiquettes de l'axe des x se trompent.
En utilisant le paramètre 'xticks', je peux passer les graduations principales à pandas.plot, puis définir les étiquettes de graduation principales. Je ne peux pas comprendre comment faire les graduations mineures en utilisant cette approche. (Je peux définir les étiquettes sur les graduations mineures par défaut définies 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 pu me rapprocher de la mise en page que je voulais en utilisant une boucle pour créer les principales étiquettes 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 faire l'axe des x en utilisant ax.annotate
: possible mais pas idéal.
la source
plot
fonction pandas et définir toutes les graduations après le traçage, en utilisant les méthodes matplotlib de l'ax
objet retourné (par exemple,ax.set_xticks
)?Réponses:
Les deux
pandas
etmatplotlib.dates
utilisermatplotlib.units
pour localiser les tiques.Mais bien qu'il
matplotlib.dates
dispose de moyens pratiques pour définir les graduations manuellement, les pandas semblent jusqu'à présent se concentrer sur le formatage automatique (vous pouvez consulter le code de conversion de date et de formatage dans les pandas).Donc pour le moment il semble plus raisonnable à utiliser
matplotlib.dates
(comme 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 [mar] devienne Dienstag [Di])
la source