pandas时间序列图设置x轴主要和次要蜱和标签
我希望能够设置大pandas时间序列对象的时间序列图中的主要和次要xticks及其标签。
pandas0.9“新到”的页面说:
“你可以使用to_pydatetime或注册转换器的时间戳types”
但我不能解决这个问题,所以我可以使用matplotlib ax.xaxis.set_major_locator
和ax.xaxis.set_major_formatter
(和minor)命令。
如果我在不转换pandas时间的情况下使用它们,则x轴刻度和标签最终会出错。
通过使用“xticks”参数,我可以将主要记号传递给pandas.plot,然后设置主要记号标签。 我无法解决如何使用这种方法做小勾号。 (我可以设置由pandas.plot设置的默认次要记号的标签)
这是我的testing代码:
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']
和它的输出:
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
更新:通过使用循环来构build主要的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'))
然而,这有点像使用ax.annotate
做x轴的可能性,但并不理想。
pandas
和matplotlib.dates
使用matplotlib.units
来定位ticks。
但是, matplotlib.dates
可以方便地手动设置刻度,pandas似乎已经把注意力集中在自动格式化上(可以看看pandasdate转换和格式化的代码 )。
所以目前来看,使用matplotlib.dates
似乎更合理(正如@BrenBarn在他的评论中提到的那样)。
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()
(我的语言环境是德语,所以星期二[Tue]变成Dienstag [Di])