Formateo de marcas de fecha usando ConciseDateFormatter #

Encontrar buenos valores de marca y formatear las marcas para un eje que tiene datos de fecha suele ser un desafío. ConciseDateFormatterestá destinado a mejorar las cadenas elegidas para las etiquetas de ticks y minimizar las cadenas utilizadas en esas etiquetas de ticks tanto como sea posible.

Nota

Este formateador es candidato para convertirse en el formateador de marca de fecha predeterminado en futuras versiones de Matplotlib. Informe cualquier problema o sugerencia para mejorar el repositorio de github o la lista de correo.

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

Primero, el formateador predeterminado.

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()
Formateador de fecha predeterminado

El formateador de fecha predeterminado es bastante detallado, por lo que tenemos la opción de usar ConciseDateFormatter, como se muestra a continuación. Tenga en cuenta que para este ejemplo no es necesario rotar las etiquetas como en el formateador predeterminado porque las etiquetas son lo más pequeñas posible.

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()
Formateador de fecha conciso

Si todas las llamadas a los ejes que tienen fechas se van a realizar con este conversor, probablemente sea más conveniente usar el registro de unidades donde se realizan las importaciones:

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()
Formateador de fecha conciso

Localización de formatos de fecha #

Los formatos de fechas se pueden localizar si los formatos predeterminados no son deseables mediante la manipulación de una de las tres listas de cadenas.

La formatter.formatslista de formatos es para las etiquetas de marca normales. Hay seis niveles: años, meses, días, horas, minutos y segundos. Así es como se formatea la formatter.offset_formatscadena de "desplazamiento" a la derecha del eje. Esto suele ser mucho más detallado que las etiquetas de marca. Finalmente, formatter.zero_formatsestán los formatos de los ticks que son "ceros". Estos son valores de marca que son el primero del año, mes o día del mes, o la hora cero, minuto o segundo. Suelen ser iguales al formato de los ticks de un nivel superior. Por ejemplo, si los límites del eje significan que los ticks son en su mayoría días, entonces etiquetamos el 1 de marzo de 2005 simplemente con "Mar". Si los límites del eje son en su mayoría horas, etiquetamos el 4 de febrero a las 00:00 simplemente como "4 de febrero".

Tenga en cuenta que estas listas de formato también se pueden pasar ConciseDateFormatter como argumentos de palabras clave opcionales.

Aquí modificamos las etiquetas para que sean "día mes año", en lugar de la ISO "año mes día":

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()
Formateador de fecha conciso

Registro de un convertidor con localización #

ConciseDateFormatterno tiene entradas rcParams, pero la localización se puede lograr pasando argumentos de palabras clave ConciseDateConvertery registrando los tipos de datos que usará con el 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()
Formateador de fecha concisa registrado como no predeterminado

Tiempo total de ejecución del script: (0 minutos 3,859 segundos)

Galería generada por Sphinx-Gallery