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:

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

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),
plt.show()