Matplotlib Date Tick Formatter

MatplotlibMatplotlibBeginner
Practice Now

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

Introduction

The ~.dates.ConciseDateFormatter is a useful tool for formatting date ticks when working with Matplotlib. In this lab, you will learn how to use this formatter to improve the strings chosen for the tick labels and to minimize the strings used in those tick labels as much as possible.

VM Tips

After the VM startup is done, click the top left corner to switch to the Notebook tab to access Jupyter Notebook for practice.

Sometimes, you may need to wait a few seconds for Jupyter Notebook to finish loading. The validation of operations cannot be automated because of limitations in Jupyter Notebook.

If you face issues during learning, feel free to ask Labby. Provide feedback after the session, and we will promptly resolve the problem for you.

Default Formatter

We begin by looking at the default formatter and its verbose output. We plot data over time and see how the default formatter displays the date and time.

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

## create time data
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))

## plot data
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()

Concise Date Formatter

Next, we explore the ~.dates.ConciseDateFormatter and its output. We create a new plot with the concise date formatter and see how it differs from the default formatter.

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()

Registering a Converter

If all calls to axes that have dates are to be made using this converter, it is probably most convenient to use the units registry. We register a converter with the units registry and plot data using the concise date formatter.

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

Localization of Date Formats

Dates formats can be localized if the default formats are not desirable by manipulating one of three lists of strings. We modify the labels to be "day month year", instead of the 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()

Registering a Converter with Localization

We can also register a converter with localization by passing keyword arguments to ~.dates.ConciseDateConverter and registering the datatypes you will use with the units registry.

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()

Summary

In this lab, you learned how to use the ~.dates.ConciseDateFormatter to format date ticks when working with Matplotlib. You also learned how to localize date formats and register converters to make the process more convenient.

Other Matplotlib Tutorials you may like