Pandas-Zeitreihen zeichnen die Haupt- und Neben-Häkchen und Beschriftungen der x-Achse ein

87

Ich möchte in der Lage sein, die Haupt- und Neben-Xticks und ihre Beschriftungen für ein Zeitreihendiagramm festzulegen, das aus einem Pandas-Zeitreihenobjekt erstellt wurde.

Auf der Seite "Was ist neu" von Pandas 0.9 heißt es:

"Sie können entweder to_pydatetime verwenden oder einen Konverter für den Zeitstempeltyp registrieren."

Aber ich kann nicht herausfinden, wie das geht, damit ich die Befehle matplotlib ax.xaxis.set_major_locatorund ax.xaxis.set_major_formatter(und minor) verwenden kann.

Wenn ich sie verwende, ohne die Pandas-Zeiten zu konvertieren, sind die Häkchen und Beschriftungen auf der x-Achse falsch.

Mit dem Parameter 'xticks' kann ich die Haupt-Ticks an pandas.plot übergeben und dann die Haupt-Tick-Beschriftungen festlegen. Ich kann nicht herausfinden, wie man die kleinen Zecken mit diesem Ansatz macht. (Ich kann die Beschriftungen auf die von pandas.plot festgelegten Standard-Minor-Ticks setzen.)

Hier ist mein Testcode:

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']

und seine Ausgabe:

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

Grafik mit seltsamen Daten auf xaxis

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

Grafik mit korrekten Daten

2011-06-04   -0.199393
2011-06-05   -0.043118
2011-06-06    0.477771
2011-06-07   -0.033207
Freq: D

Update: Ich konnte dem gewünschten Layout näher kommen, indem ich eine Schleife zum Erstellen der wichtigsten xtick-Labels verwendete:

# 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'))

Dies ist jedoch ein bisschen wie bei der x-Achse mit ax.annotate: möglich, aber nicht ideal.

brenda
quelle
1
Ich weiß, dass dies die Frage nicht wirklich beantwortet, aber als allgemeiner Ansatz, wenn ich mich wirklich darum kümmere, wie ein Plot aussieht, versuche ich im Allgemeinen nur, eine Vektorversion davon zu erhalten und sie in Illustrator oder Inkscape schön aussehen zu lassen. Ich habe festgestellt, dass die meisten anderen Leute, die ich kenne, dasselbe tun.
John McDonnell
2
Können Sie die Argumente für die Pandas- plotFunktion einfach völlig ignorieren und alle Häkchen nach dem Plotten setzen, indem Sie die matplotlib-Methoden des zurückgegebenen axObjekts verwenden (z. B. ax.set_xticks)?
BrenBarn
@BrenBarn Ich konnte nicht herausfinden, wie das Datum als Python-Datum anstelle einer Pandas-Datumszeit für die matplotlib-Methoden abgerufen werden kann. Die Antwort von bmu behebt dies, indem die Daten vor dem Plotten konvertiert werden.
Brenda

Antworten:

89

Sowohl pandasund matplotlib.datesVerwendung matplotlib.unitsfür die Zecken zu lokalisieren.

Obwohl matplotlib.dateses bequeme Möglichkeiten gibt, die Häkchen manuell zu setzen, scheint sich Pandas bisher auf die automatische Formatierung zu konzentrieren (Sie können sich den Code für die Datumskonvertierung und Formatierung in Pandas ansehen ).

Im Moment scheint es also vernünftiger zu sein matplotlib.dates(wie von @BrenBarn in seinem Kommentar erwähnt).

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()

pandas_like_date_fomatting

(Mein Gebietsschema ist Deutsch, so dass Dienstag [Di] Dienstag [Di] wird.)

bmu
quelle