Pandas时间序列绘图设置x轴主刻度和次刻度和标签

vcirk6k6  于 2023-08-01  发布在  其他
关注(0)|答案(3)|浏览(158)

我希望能够为从Pandas时间序列对象绘制的时间序列图设置主要和次要xtick及其标签。
Pandas 0.9“What's new”页面说:
“您可以使用to_pydatetime或注册Timestamp类型的转换器”
但我不知道如何做到这一点,以便我可以使用matplotlib ax.xaxis.set_major_locatorax.xaxis.set_major_formatter(和minor)命令。
如果我使用它们而不转换pandas时间,x轴刻度和标签最终会出错。
通过使用'xticks'参数,我可以将主要标记传递给pandas的.plot,然后设置主要标记标签。我无法使用这种方法计算出如何进行次要标记(我可以在pandas的.plot设置的默认次要标记上设置标签)。
下面是我的测试代码:

xaxis上带有奇怪日期的图表

import pandas as pd
import matplotlib.dates as mdates
import numpy as np

dateIndex = pd.date_range(start='2011-05-01', end='2011-07-01', freq='D')
testSeries = pd.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(mdates.WeekdayLocator())
ax.xaxis.set_minor_formatter(mdates.DateFormatter('%d\n%a'))
ax.xaxis.grid(True, which="minor")
ax.xaxis.grid(False, which="major")
ax.xaxis.set_major_formatter(mdates.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 = pd.date_range(start='2011-05-01', end='2011-07-01', freq='W-Tue')
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]);
# remove the minor xtick labels set by pandas.plot 
ax2.set_xticklabels([], minor=True)
# turn the minor ticks created by pandas.plot off 
plt.show()


**更新:**我已经能够通过使用循环来构建主要的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时间序列数据时,如何设置主刻度和次刻度?

8yoxcaq7

8yoxcaq71#

pandasmatplotlib.dates都使用matplotlib.units定位刻度。
但是,虽然matplotlib.dates有方便的方法来手动设置刻度,但到目前为止,pandas似乎专注于自动格式化(你可以看看code在pandas中的日期转换和格式化)。
因此,目前使用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()

字符串
x1c 0d1x的数据
(my”““”

gzszwxb4

gzszwxb42#

要关闭Pandas日期时间刻度调整,必须添加参数x_compat=True
范例:

ds.plot(x_compat=True)

字符串
请参阅Pandas文档中的更多示例:抑制刻度分辨率调整

ecr0jaav

ecr0jaav3#

在matplotlib的plot()中,默认的时间序列单位是1天,但在pandas的plot()中,1单位等于时间序列的频率,所以如果频率是1天,1单位就是1天;如果是1小时,则是1小时等等。这使得matplotlib和pandas的plot()调用在时间序列数据上有所不同。
如果时间序列的频率为1天,则matplotlib.dates.WeekdayLocatormatplotlib.dates.MonthLocator等。可以“定位”tick位置1,因为pandas plot()使用1天作为创建xtick位置的基本单位(与matplotlib的默认值一致)。
由于pandas的plot()调用返回Axes对象,因此可以使用matplotlib.dates修改Axes对象的刻度标签。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

idx = pd.date_range('2011-05-01', '2011-07-01', freq='D')
s1 = pd.Series(np.random.randn(len(idx)), index=idx)

ax = s1.plot(style='v-')
ax.xaxis.set(
    minor_locator=mdates.WeekdayLocator(),               # make minor ticks on each Tuesday
    minor_formatter=mdates.DateFormatter('%d\n%a'),      # format minor ticks
    major_locator=mdates.MonthLocator(),                 # make major ticks on first day of each month
    major_formatter=mdates.DateFormatter('\n\n\n%b\n%Y') # format major ticks
);

字符串
x1c 0d1x的数据
然而,如果频率不是1天,而是1周,那么matplotlib.dates将无法定位位置,因为,如前所述,pandas的plot()将单位设置为与时间序列频率(1周)相同,这“混淆”了matplotlib.dates。因此,如果我们尝试使用设置s1的刻度标签相同的代码来设置s2的刻度标签,那么我们将得到非常错误的刻度标签。
要“解决”这个问题,一种方法是通过传递x_compat=True来删除pandas的自动刻度分辨率调整。然后可以使用matplotlib的分辨率设置主/次刻度标签;换句话说,它可以以与上述相同的方式设置。

idx = pd.date_range('2011-05-01', '2011-07-01', freq='W')
s2 = pd.Series(np.random.randn(len(idx)), index=idx)

ax = s2.plot(style='v-', x_compat=True, rot=0)
ax.xaxis.set(
    minor_locator=mdates.WeekdayLocator(),              # make minor ticks on each Tuesday
    minor_formatter=mdates.DateFormatter('%d'),         # format minor ticks
    major_locator=mdates.MonthLocator(),                # make major ticks on first day of each month
    major_formatter=mdates.DateFormatter('\n\n%b\n%Y')  # format major ticks
);



解决这个问题的另一种方法是使用matplotlib的plot()来代替(正如@bmu所建议的那样)。因为matplotlib中的单位是固定的,所以我们可以像上面那样设置刻度标签,没有问题。

plt.plot(s2.index, s2, 'v-')                            # use matplotlib instead
plt.gca().xaxis.set(
    minor_locator=mdates.WeekdayLocator(byweekday=0),   # make minor ticks on each Monday
    minor_formatter=mdates.DateFormatter('%d'),         # format minor ticks
    major_locator=mdates.MonthLocator(),                # make major ticks on first day of each month
    major_formatter=mdates.DateFormatter('\n\n%b\n%Y')  # format major ticks
);


1 matplotlib.dates.num2timedelta(1) == datetime.timedelta(days=1)为真。

相关问题