Latest cool features of Matplotlib | by Ankit Gupta | Towards Data Science

A few days ago, Matplotlib released version 3.3 — the latest in the third generation of its family. It introduced some really exciting features and I would strongly recommend you to upgrade your Matplotlib today. This post will guide you through them using some examples.
I updated to the latest version in my virtual environment using the following command. For fresh installations, refer to the official installation guidelines.
pip install matplotlib --upgrade
Let’s take a look at the latest highlight features of Matplotlib 3.3.
A much less verbose way to generate subplots, which allows you to visually layout your axes in a semantic manner, is introduced via subplot_mosaic(). Earlier, you had to use comparatively more verbose methods of subplots()orGridSpec. You can, moreover, name your axes as you like.
For example, to generate the grid shown below, you can now pass the layout in the form of a list. A missing subplot is indicated as '.'. To span a subplot over two columns, repeat the name as I did for 'bar'. To span across rows (vertically), use the same name vertically below in the second list. The names 'bar', 'hist', and 'scatter' can also be used to control/modify the properties of the corresponding subplots.
This feature is quite cool and broad, and you should read in detail about this complex and semantic figure composition here. This hyperlink also shows you other short-hand ASCII notations to recreate the figure below.
axes = plt.figure(constrained_layout=True).subplot_mosaic(                [['.', 'bar', 'bar'], # Note repitition of 'bar'                 ['hist', '.', 'scatter']])for k, ax in axes.items():    ax.text(0.5, 0.5, k, ha='center', va='center',             fontsize=36, color='magenta')
You can also now share the axes among different subplots immediately upon their creation as exemplified here.
The aspect ratio of the axes box is the height of the axes divided by its width in physical units. So if you need a square box, the box aspect ratio will be 1. Now, you can directly set this ratio via set_box_aspect() method as shown below. Several use cases of this feature are provided here. In the code below, comment out the last two lines to see the change in the axes box aspect ratio.
fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)ax1.plot(np.random.randint(0, 100, 1000), 'go')ax2.plot([300, 900], [20, 55], 'g')ax1.set_box_aspect(1)ax2.set_box_aspect(1)
You can specify the color of the legend text labels while invoking the legend using the keyword argument labelcolor. By default, it is always black.
Even better: If your figure has both lines and markers with different colors for the line, the marker face, and the marker edge, you can choose the text color to match their respective colors by specifying either of the 'linecolor', 'markerfacecolor', or'markeredgecolor'.
See the example below where I set the label’s color to the marker face color:
fig = plt.figure()x = np.linspace(0, 2*np.pi, 500)plt.plot(x, np.sin(x**2), '-o', c='orangered', mfc='b',         lw=3, markevery=4, label=r'sin($x^2$)')plt.legend(fontsize=20, labelcolor='markerfacecolor',           handlelength=1)
Matplotlib 3.3 now also offers Google AI team’s turbo colormap.
Now, you can align the x- and y-axes labels, each in three locations. The x-label can be aligned to the left, center, or right of the x-axis. Similarly, the y-label can be aligned at the top, center, or bottom of the y-axis. This can be done using the parameter loc. The following example illustrates this:
plt.xlabel(r"$x$ (radians)", loc='right', fontsize=18)plt.ylabel(r"sin($x^2$)", loc='bottom', fontsize=18)
It is now much less verbose to set the tick formatting on the axes. For example, you can now directly use strings or functions as input to the string formatters. The following code snippet compares the latest way of formatting using a string with the old way. You can clearly see how simple the latest method is. See this example for the similar use of lambda functions.
import matplotlib.ticker as mticker# Plot the sinusoidal function# In latest version 3.3 ax.xaxis.set_major_formatter('{x:.0f} rad')# Before version 3.3ax.xaxis.set_major_formatter(mticker.StrMethodFormatter('{x:.0f}                              rad'))
This is a really cool feature. You can now wrap your functions with custom decorators to control the parameters for your plots. In the example below, I decorate the function to plot a sine curve with custom rcParams settings.
from matplotlib import rc_context@rc_context({"lines.linewidth": 6,              'figure.facecolor': 'lightgreen',             'legend.fontsize': 18})def plot_sin(x):    fig, ax = plt.subplots(figsize=(6, 4))    ax.plot(x, np.sin(x**2), label=r'sin($x^2$)')    ax.legend()    returnplot_sin(x)
So far, there was no direct way to enable minor ticks on 3D axes. Now you can simply turn them on using the keyword minor=True. Adapting the official example, I show this feature below applied to the z-axis.
from mpl_toolkits.mplot3d import Axes3Dfig = plt.figure()ax = fig.add_subplot(projection='3d')ax.scatter([0, 1, 2], [1, 3, 5], [30, 50, 70])ax.set_zticks([35, 45, 55, 65], minor=True)ax.set_zticklabels([r'$\alpha$', r'$\beta$', r'$\delta$',                    r'$\gamma$'], minor=True)ax.tick_params(which='major', color='r', labelcolor='r', width=5)ax.tick_params(which='minor', color='b', labelcolor='b', width=3)
Now, you do not need to specify the backend explicitly at the beginning of your Jupyter Notebooks globally. You can simply pass the desired backend as an argument while saving the figure using the backend keyword. For example, if you want to save a pdf figure with a pgf backend, you can do the following
plt.savefig('/Users/Henry/Downloads/sinusoidal.pdf', backend="pgf")
You can read more on backends in matplotlib here.
Now you can draw infinitely long lines passing through two points directly using the newly introduced axline method. There are two options: Either you can specify both points explicitly and let the system compute the slope, or you specify one point and the slope of the line. The below example shows the usage of both options.
Remember: The keyword slope should only be used with linear scales. For all non-linear scales, you have to pass both points explicitly.
fig, ax = plt.subplots(figsize=(6, 4))ax.axline((.4, .4), slope=5, color='r', label='using slope')ax.axline((.3, .4), (.5, .6), color='b', label='using points')ax.legend(fontsize=18, frameon=False)
Although there are several other interesting features introduced in the latest version 3.3, I would keep this post short and recommend you to refer to read the official page here for the complete list of introduced changes.
If you are interested in knowing what’s new in the previous Matplotlib versions 3.0, 3.1, and 3.3, read my earlier post What’s New in Matplotlib 3.