2012-10-18 4 views
74

Ich möchte in der Lage sein, die großen und kleinen Xticks und ihre Bezeichnungen für eine Zeitreihe Grafik von einem Pandas Zeitreihenobjekt geplottet. DiePandas Zeitreihen Plot Einstellung X-Achse Haupt- und Neben Ticks und Labels

Pandas 0.9 „Neue Funktionen“ Seite sagt:

„Sie entweder to_pydatetime verwenden oder einen Konverter für die Timestamp-Typ-Register“

aber ich kann nicht herausfinden, wie um das zu tun, so dass ich die Matplotlib ax.xaxis.set_major_locator und ax.xaxis.set_major_formatter (und kleinere) Befehle verwenden kann.

Wenn ich sie benutze, ohne die Pandas Zeiten zu konvertieren, enden die X-Achse Ticks und Beschriftungen falsch.

Mit dem Parameter 'xticks' kann ich die Haupt-Ticks an pandas.plot übergeben und dann die wichtigsten Tick-Labels festlegen. Ich kann nicht herausfinden, wie man die kleinen Ticks mit diesem Ansatz macht. (Ich kann die Etiketten auf den Standard-Moll-Ticks von pandas.plot eingestellt)

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 

Graph with strange dates on 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 

Graph with correct dates

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

Update: Ich habe in der Lage gewesen, um das Layout näher komme ich durch die Verwendung einer Schleife zu bauen, um die großen Xtick Labels wollten:

# 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 zu tun die x -Achse mit ax.annotate: möglich, aber nicht ideal.

+1

Ich weiß, das ist wirklich nicht die Frage beantworten, sondern als allgemeiner Ansatz, wenn Ich sorge mich wirklich darum, wie eine Handlung aussieht, im Allgemeinen versuche ich einfach, eine Vektorversion davon zu bekommen und es in Illustrator oder Inkscape schön aussehen zu lassen. Ich habe die meisten anderen Leute gefunden, von denen ich weiß, dass sie dasselbe tun. –

+2

Kannst du die Argumente für die "Plot" -Funktion der Pandas einfach ignorieren und alle Ticks nach dem Plotten setzen, indem du die Matplotlib-Methoden des zurückgegebenen 'ax'-Objekts verwendest (z. B.' ax.set_xticks')? – BrenBarn

+0

@BrenBarn Ich konnte nicht herausfinden, wie man das Datum als Python-Datum anstelle von Pandas Datetime für die Matplotlib-Methoden erhält. Die Antwort von bmu behebt das durch das Konvertieren der Daten vor dem Plotten. – brenda

Antwort

69

Sowohl pandas als auch matplotlib.dates verwenden Sie matplotlib.units zum Auffinden der Ticks.

Aber während matplotlib.dates bequeme Möglichkeiten hat, die Ticks manuell einzustellen, scheint Pandas den Fokus auf die automatische Formatierung so weit zu haben (Sie können einen Blick auf die code für Datum Konvertierung und Formatierung in Pandas).

Für den Moment scheint es vernünftiger zu sein, matplotlib.dates zu verwenden (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

(meine locale ist Deutsch, so dass Dienstag [Di] wird Dienstag [Di])

+0

Danke, dies ist ein sehr klares Beispiel für die Verwendung von Matplotlib mit Pandas-Zeitreihendaten. Ich wusste nicht, dass du eine Serie als Daten an Matplotlib übergeben kannst, so wie du es getan hast. – brenda

Verwandte Themen