Formatando marcações de data usando ConciseDateFormatter #

Encontrar bons valores de tick e formatar os ticks para um eixo que possui dados de data geralmente é um desafio. ConciseDateFormatterdestina-se a melhorar as strings escolhidas para os ticklabels e minimizar as strings usadas nesses rótulos de ticks tanto quanto possível.

Observação

Este formatador é um candidato a se tornar o formatador de marca de data padrão em versões futuras do Matplotlib. Por favor, relate quaisquer problemas ou sugestões de melhoria para o repositório github ou lista de discussão.

import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np

Primeiro, o formatador padrão.

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, constrained_layout=True, 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()
Formatador de data padrão

O formatador de data padrão é bastante detalhado, então temos a opção de usar ConciseDateFormatter, conforme mostrado abaixo. Observe que, para este exemplo, os rótulos não precisam ser girados como no formatador padrão, porque os rótulos são os menores possíveis.

fig, axs = plt.subplots(3, 1, constrained_layout=True, 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()
Formatador de data concisa

Se todas as chamadas para os eixos que possuem datas devem ser feitas usando este conversor, provavelmente é mais conveniente usar o registro de unidades onde você faz as importações:

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), constrained_layout=True)
for nn, ax in enumerate(axs):
    ax.plot(dates, y)
    ax.set_xlim(lims[nn])
axs[0].set_title('Concise Date Formatter')

plt.show()
Formatador de data concisa

Localização de formatos de data #

Os formatos de datas podem ser localizados se os formatos padrão não forem desejáveis, manipulando uma das três listas de strings.

A formatter.formatslista de formatos é para os rótulos de escala normais. Existem seis níveis: anos, meses, dias, horas, minutos, segundos. É formatter.offset_formatsassim que a string de "deslocamento" à direita do eixo é formatada. Isso geralmente é muito mais detalhado do que os rótulos de escala. Finalmente, formatter.zero_formatssão os formatos dos ticks que são "zeros". Esses são valores de escala que são o primeiro dia do ano, mês ou dia do mês, ou a hora, minuto ou segundo zero. Estes são geralmente os mesmos que o formato dos ticks de um nível acima. Por exemplo, se os limites do eixo significam que os ticks são principalmente dias, então rotulamos 1º de março de 2005 simplesmente com "Mar". Se os limites do eixo forem principalmente horas, rotularemos 4 de fevereiro 00:00 simplesmente como "4 de fevereiro".

Observe que essas listas de formato também podem ser passadas ConciseDateFormatter como argumentos de palavra-chave opcionais.

Aqui, modificamos os rótulos para "dia, mês, ano", em vez do ISO "ano, mês, dia":

fig, axs = plt.subplots(3, 1, constrained_layout=True, 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()
Formatador de data concisa

Registrando um conversor com localização #

ConciseDateFormatternão possui entradas rcParams, mas a localização pode ser realizada passando argumentos de palavra-chave ConciseDateConvertere registrando os tipos de dados que você usará com o registro de unidades:

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 its 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, constrained_layout=True, 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 registrado como não padrão

Tempo total de execução do script: (0 minutos 3,859 segundos)

Galeria gerada por Sphinx-Gallery