A new version of matplotlib was released on the 26th of March 2021. This article will go over VersionBay’s favorite new features.

Before looking at the latest version it is interesting to see the release history of matplotlib:

Matplotlib VersionRelease DateDays
3.426 March 2021252
3.317 July 2020135
3.24 March 2020291
3.118 May 2019239
3.021 September 2018199
2.26 March 2018144
2.113 October 2017235
2.020 February 2017484
1.529 October 2015418
1.42 September 2014398
1.331 July 2013
Release history for matplotlib

It is also worth noticing looking at the minimum requirements of Python and NumPy for each release of matplotlib (see here for more details).

MatplotlibPythonNumPy
3.43.71.16.0
3.33.61.15.0
3.23.61.11.0
3.13.61.11.0
3.03.51.10.0
2.22.7, 3.41.7.1
2.12.7, 3.41.7.1
2.02.7, 3.41.7.1
Minimum requirements for matplotlib

VersionBay looked at the release notes choose the following ones:

Here are some code snippets that show why some of these caught VersionBay’s attention. Please note that there is no particular order to this list.

Now supports overset and underset LaTeX symbols

This is not a game-changer but certainly nice to see additional support of LaTeX symbols when writing text with matplotlib.

import matplotlib.pyplot as plt


math_expr = r"$ x \overset{f}{\rightarrow} y \underset{f}{\leftarrow} z $"
plt.text(0.4, 0.5, math_expr, usetex=False)

New automatic labeling for bar charts

This is a nice addition to bar charts. Excel has had this for many years, so now there is really no excuse.

import numpy as np
import matplotlib.pyplot as plt


N = 5
menMeans = (20, 35, 30, 35, -27)
womenMeans = (25, 32, 34, 20, -25)
menStd = (2, 3, 4, 1, 2)
womenStd = (3, 5, 2, 3, 3)
ind = np.arange(N)    # the x locations for the groups
width = 0.35       # the width of the bars: can also be len(x) sequence

fig, ax = plt.subplots()

p1 = ax.bar(ind, menMeans, width, yerr=menStd, label='Men')
p2 = ax.bar(ind, womenMeans, width,
            bottom=menMeans, yerr=womenStd, label='Women')

ax.axhline(0, color='grey', linewidth=0.8)
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind)
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
ax.legend()

# Label with label_type 'center' instead of the default 'edge'
ax.bar_label(p1, label_type='center')
ax.bar_label(p2, label_type='center')
ax.bar_label(p2)
plt.show()

TickedStroke patheffect

It can be hard to visualize boundary conditions. With this new feature is makes it easier to illustrate this.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patheffects as patheffects


fig, ax = plt.subplots(figsize=(6, 6))
ax.plot([0, 1], [0, 1], label="Line",
        path_effects=[patheffects.withTickedStroke(spacing=7, angle=135)])

nx = 101
x = np.linspace(0.0, 1.0, nx)
y = 0.3*np.sin(x*8) + 0.4
ax.plot(x, y, label="Curve", path_effects=[patheffects.withTickedStroke()])

ax.legend()
plt.show()

hexbin supports data reference for C parameter

Typically people who have tried to use hexbin always find the color dimension a little hard to get right. Very happy to see that it is much easier to control and understand. See how the second chart is what one would more naturally expect.

import numpy as np
import matplotlib.pyplot as plt


data = {
    'a': np.arange(0,1000),
    'b': np.arange(0,1000),
    'c': np.arange(0,1000)
}

fig, ax = plt.subplots()
ax.hexbin('a', 'b', C='c', data=data, gridsize=10) # 'C' is now supported
# ax.hexbin('a', 'b', data=data, gridsize=10)
pl.show()

Support callable for formatting of Sankey labels

Sankey charts are always interesting and help tell flow data in a more intuitive way. Historically one has only been able to put text with limited formatting on the edges. With matplotlib 3.4 one can customize formatting with callable functions. This example came from matplotlib release notes but illustrates the point very clearly.

import matplotlib.pyplot as plt
from matplotlib.sankey import Sankey
import math


def display_in_cats(values, min_cats, max_cats):
    def display_in_cat_scale(value):
        max_value = max(values, key=abs)
        number_cats_to_show = \
            max(min_cats, math.floor(abs(value) / max_value * max_cats))
        return str(number_cats_to_show * '🐱')

    return display_in_cat_scale


flows = [35, 15, 40, -20, -15, -5, -40, -10]
orientations = [-1, 1, 0, 1, 1, 1, -1, -1]

# Cats are good, we want a strictly positive number of them
min_cats = 1
# More than four cats might be too much for some people
max_cats = 4


sankey = Sankey(flows=flows, orientations=orientations, format=display_in_cats(flows, min_cats, max_cats),
                 offset=.1, head_angle=180, shoulder=0, scale=.010)


diagrams = sankey.finish()

diagrams[0].texts[2].set_text('')

plt.title(f'Sankey flows measured in cats \n'
          f'🐱 = {max(flows, key=abs) / max_cats}')
plt.show()

For more information, we recommend reading the changelog from matplotlib.

If you found this article interesting and would like to learn more about Python Contact Us.