简介
~.dates.ConciseDateFormatter 是在使用 Matplotlib 时格式化日期刻度的一个有用工具。在本实验中,你将学习如何使用这个格式化器来改进为刻度标签选择的字符串,并尽可能减少这些刻度标签中使用的字符串。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到“笔记本”标签页,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。
默认格式化器
我们首先来看默认格式化器及其冗长的输出。我们绘制随时间变化的数据,并观察默认格式化器如何显示日期和时间。
import datetime
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
## 创建时间数据
base = datetime.datetime(2005, 2, 1)
dates = [base + datetime.timedelta(hours=(2 * i)) for i in range(732)]
N = len(dates)
np.random.seed(19680801)
y = np.cumsum(np.random.randn(N))
## 绘制数据
fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(6, 6))
lims = [(np.datetime64('2005-02'), np.datetime64('2005-04')),
(np.datetime64('2005-02-03'), np.datetime64('2005-02-15')),
(np.datetime64('2005-02-03 11:00'), np.datetime64('2005-02-04 13:20'))]
for nn, ax in enumerate(axs):
ax.plot(dates, y)
ax.set_xlim(lims[nn])
## 旋转标签...
for label in ax.get_xticklabels():
label.set_rotation(40)
label.set_horizontalalignment('right')
axs[0].set_title('默认日期格式化器')
plt.show()
简洁日期格式化器
接下来,我们探索 ~.dates.ConciseDateFormatter 及其输出。我们使用简洁日期格式化器创建一个新的图表,并观察它与默认格式化器有何不同。
fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(6, 6))
for nn, ax in enumerate(axs):
locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(dates, y)
ax.set_xlim(lims[nn])
axs[0].set_title('简洁日期格式化器')
plt.show()
注册一个转换器
如果所有对包含日期的坐标轴的调用都要使用这个转换器来进行,那么使用单位注册表可能是最方便的。我们向单位注册表注册一个转换器,并使用简洁日期格式化器绘制数据。
import datetime
import matplotlib.units as munits
converter = mdates.ConciseDateConverter()
munits.registry[np.datetime64] = converter
munits.registry[datetime.date] = converter
munits.registry[datetime.datetime] = converter
fig, axs = plt.subplots(3, 1, figsize=(6, 6), layout='constrained')
for nn, ax in enumerate(axs):
ax.plot(dates, y)
ax.set_xlim(lims[nn])
axs[0].set_title('简洁日期格式化器')
plt.show()
日期格式的本地化
如果默认格式不符合需求,可以通过操作三个字符串列表之一来实现日期格式的本地化。我们将标签修改为“日 月 年”,而不是 ISO 格式的“年 月 日”。
fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(6, 6))
for nn, ax in enumerate(axs):
locator = mdates.AutoDateLocator()
formatter = mdates.ConciseDateFormatter(locator)
formatter.formats = ['%y', ## 刻度大多是年份
'%b', ## 刻度大多是月份
'%d', ## 刻度大多是日期
'%H:%M', ## 小时
'%H:%M', ## 分钟
'%S.%f', ] ## 秒
## 这些大多只是上一级的格式...
formatter.zero_formats = [''] + formatter.formats[:-1]
#...除了刻度大多是小时的情况,此时最好有
## 月 - 日:
formatter.zero_formats[3] = '%d-%b'
formatter.offset_formats = ['',
'%Y',
'%b %Y',
'%d %b %Y',
'%d %b %Y',
'%d %b %Y %H:%M', ]
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(dates, y)
ax.set_xlim(lims[nn])
axs[0].set_title('简洁日期格式化器')
plt.show()
注册带有本地化的转换器
我们还可以通过向 ~.dates.ConciseDateConverter 传递关键字参数,并向单位注册表注册你将使用的数据类型,来注册一个带有本地化的转换器。
import datetime
formats = ['%y', ## 刻度大多是年份
'%b', ## 刻度大多是月份
'%d', ## 刻度大多是日期
'%H:%M', ## 小时
'%H:%M', ## 分钟
'%S.%f', ] ## 秒
## 这些可以相同,只是偏移一个级别....
zero_formats = [''] + formats[:-1]
#...除了刻度大多是小时的情况,此时有月 - 日格式会更好
zero_formats[3] = '%d-%b'
offset_formats = ['',
'%Y',
'%b %Y',
'%d %b %Y',
'%d %b %Y',
'%d %b %Y %H:%M', ]
converter = mdates.ConciseDateConverter(
formats=formats, zero_formats=zero_formats, offset_formats=offset_formats)
munits.registry[np.datetime64] = converter
munits.registry[datetime.date] = converter
munits.registry[datetime.datetime] = converter
fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(6, 6))
for nn, ax in enumerate(axs):
ax.plot(dates, y)
ax.set_xlim(lims[nn])
axs[0].set_title('注册了非默认格式的简洁日期格式化器')
plt.show()
总结
在这个实验中,你学习了如何在使用 Matplotlib 时使用 ~.dates.ConciseDateFormatter 来格式化日期刻度。你还学习了如何本地化日期格式以及注册转换器,以使这个过程更加便捷。