使用 ConciseDateFormatter 格式化日期刻度线#

为具有日期数据的轴找到合适的刻度线值并格式化刻度线通常是一个挑战。 ConciseDateFormatter 旨在改进为刻度线标签选择的字符串,并尽可能减少这些刻度线标签中使用的字符串。

注意

此格式化器有望成为未来版本 Matplotlib 中的默认日期刻度线格式化器。请将任何问题或改进建议报告给 GitHub 存储库或邮件列表。

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])
    # rotate_labels...
    for label in ax.get_xticklabels():
        label.set_rotation(40)
        label.set_horizontalalignment('right')
axs[0].set_title('Default Date Formatter')
plt.show()
Default Date Formatter

默认日期格式化器非常冗长,因此我们可以选择使用 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('Concise Date Formatter')

plt.show()
Concise Date Formatter

如果所有对具有日期的轴的调用都要使用此转换器,则在导入时使用单位注册表可能最方便

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('Concise Date Formatter')

plt.show()
Concise Date Formatter

日期格式的本地化#

如果默认格式不合适,可以通过操作三个字符串列表之一来本地化日期格式。

用于普通刻度线标签的 formatter.formats 字符串列表。共有六个级别:年份、月份、日期、小时、分钟、秒。 formatter.offset_formats 用于格式化轴右侧的“偏移”字符串。这通常比刻度线标签冗长得多。最后, formatter.zero_formats 是“零”刻度线的格式。这些是值为一年、一月或一天的开始,或为零小时、分钟或秒的刻度线值。这些通常与上一级刻度线的格式相同。例如,如果轴限制意味着刻度线主要为日期,那么我们将 2005 年 3 月 1 日简单地标记为“Mar”。如果轴限制主要为小时,那么我们将 2 月 4 日 00:00 简单地标记为“Feb-4”。

请注意,这些格式列表也可以作为可选关键字参数传递给 ConciseDateFormatter

这里我们将标签修改为“day month year”,而不是 ISO 格式的“year month day”

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',  # ticks are mostly years
                         '%b',       # ticks are mostly months
                         '%d',       # ticks are mostly days
                         '%H:%M',    # hrs
                         '%H:%M',    # min
                         '%S.%f', ]  # secs
    # these are mostly just the level above...
    formatter.zero_formats = [''] + formatter.formats[:-1]
    # ...except for ticks that are mostly hours, then it is nice to have
    # month-day:
    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('Concise Date Formatter')

plt.show()
Concise Date Formatter

使用本地化注册转换器#

ConciseDateFormatter 没有 rcParams 条目,但可以通过将关键字参数传递给 ConciseDateConverter 并使用单位注册表注册您将使用的 datatype 来实现本地化

import datetime

formats = ['%y',          # ticks are mostly years
           '%b',     # ticks are mostly months
           '%d',     # ticks are mostly days
           '%H:%M',  # hrs
           '%H:%M',  # min
           '%S.%f', ]  # secs
# these can be the same, except offset by one level....
zero_formats = [''] + formats[:-1]
# ...except for ticks that are mostly hours, then it's nice to have month-day
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('Concise Date Formatter registered non-default')

plt.show()
Concise Date Formatter registered non-default

脚本的总运行时间:(0 分钟 4.728 秒)

由 Sphinx-Gallery 生成的图库