Matplotlib 日期刻度格式化器

MatplotlibMatplotlibBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

~.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 来格式化日期刻度。你还学习了如何本地化日期格式以及注册转换器,以使这个过程更加便捷。