Observação
Clique aqui para baixar o código de exemplo completo
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. ConciseDateFormatter
destina-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()
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()
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()
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.formats
lista de formatos é para os rótulos de escala normais. Existem seis níveis: anos, meses, dias, horas, minutos, segundos. É formatter.offset_formats
assim que a string de "deslocamento" à direita do eixo é formatada. Isso geralmente é muito mais detalhado do que os rótulos de escala. Finalmente, formatter.zero_formats
sã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()
Registrando um conversor com localização #
ConciseDateFormatter
não possui entradas rcParams, mas a localização pode ser realizada passando argumentos de palavra-chave ConciseDateConverter
e 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()
Tempo total de execução do script: (0 minutos 3,859 segundos)