Rangkaian waktu Pandas merencanakan pengaturan centang dan label sumbu x mayor dan minor

87

Saya ingin dapat mengatur xticks mayor dan minor serta labelnya untuk grafik deret waktu yang diplot dari objek deret waktu Pandas.

Halaman "apa yang baru" di Pandas 0.9 mengatakan:

"Anda dapat menggunakan to_pydatetime atau mendaftarkan konverter untuk jenis Timestamp"

tetapi saya tidak dapat mengetahui cara melakukannya sehingga saya dapat menggunakan perintah matplotlib ax.xaxis.set_major_locatordan ax.xaxis.set_major_formatter(dan minor).

Jika saya menggunakannya tanpa mengonversi waktu panda, tanda centang dan label sumbu x berakhir salah.

Dengan menggunakan parameter 'xticks' saya bisa meneruskan tanda centang utama ke pandas.plot, dan kemudian mengatur label tanda centang utama. Saya tidak tahu bagaimana melakukan kutu kecil menggunakan pendekatan ini. (Saya dapat mengatur label pada tanda centang minor default yang ditetapkan oleh pandas.plot)

Ini kode tes saya:

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

dan keluarannya:

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 dengan tanggal aneh pada 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

Buat grafik dengan tanggal yang benar

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

Pembaruan: Saya bisa lebih dekat dengan tata letak yang saya inginkan dengan menggunakan loop untuk membangun label xtick utama:

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

Namun, ini seperti melakukan sumbu x menggunakan ax.annotate: mungkin tetapi tidak ideal.

brenda
sumber
1
Saya tahu ini tidak benar-benar menjawab pertanyaannya, tetapi sebagai pendekatan umum ketika saya benar-benar peduli tentang tampilan plot, saya biasanya hanya mencoba mendapatkan versi vektornya dan membuatnya terlihat bagus di Illustrator atau Inkscape. Saya telah menemukan bahwa kebanyakan orang lain yang saya kenal tampaknya melakukan hal yang sama.
John McDonnell
2
Bisakah Anda mengabaikan argumen ke plotfungsi pandas dan mengatur semua tanda centang setelah memplot, dengan menggunakan metode matplotlib dari axobjek yang dikembalikan (misalnya, ax.set_xticks)?
BrenBarn
@BrenBarn Saya tidak tahu bagaimana mendapatkan tanggal sebagai tanggal python alih-alih tanggal waktu panda untuk metode matplotlib. Jawaban oleh bmu memperbaikinya dengan mengubah tanggal sebelum merencanakan.
brenda

Jawaban:

89

Keduanya pandasdan matplotlib.datesdigunakan matplotlib.unitsuntuk menemukan kutu.

Namun, meskipun matplotlib.datesmemiliki cara mudah untuk menyetel kutu secara manual, sejauh ini panda tampaknya memiliki fokus pada pemformatan otomatis (Anda dapat melihat kode untuk konversi dan pemformatan tanggal dalam panda).

Jadi untuk saat ini sepertinya lebih masuk akal untuk digunakan matplotlib.dates(seperti yang disebutkan oleh @BrenBarn dalam komentarnya).

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

(lokal saya adalah Jerman, sehingga Selasa [Sel] menjadi Dienstag [Di])

bmu
sumber