Skip to content

Advanced Matplotlib Concepts

In this section we cover some more advanced topics which you won't usually use as often.

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 25) # points xn = 5n/24, n=0..24

Logarithmic Scale

It is possible to set a logarithmic scale for one or both axes. This functionality is in fact only one application of a more general transformation system in Matplotlib. Each of the axes' scales are set separately using set_xscale and set_yscale methods which accept one parameter (with the value "log" in this case).

fig, axes = plt.subplots(1, 2, figsize=(10,4)) # nrows=1, ncols=2

axes[0].plot(x, x**2, x, np.exp(x)) # two plots y=x^2, y=e^x
axes[0].set_title("Normal scale")

axes[1].plot(x, x**2, x, np.exp(x))
axes[1].set_yscale("log")
axes[1].set_title("Logarithmic scale (y)");

Graph Graph

Axes

Axis Ticks and Tick Labels

We can explicitly determine where we want the axis ticks with set_xticks and set_yticks, which both take a list of values for where on the axis the ticks are to be placed. We can also use the set_xticklabels and set_yticklabels methods to provide a list of custom text labels for each tick location.

fig, ax = plt.subplots(figsize=(10, 4))

ax.plot(x, x**2, x, x**3, lw=2)

ax.set_xticks([1, 2, 3, 4, 5])
# use LaTeX formatted labels
ax.set_xticklabels([r'$\alpha$', r'$\beta$', r'$\gamma$',
                r'$\delta$', r'$\epsilon$'], fontsize=18)

yticks = [0, 50, 100, 150]
ax.set_yticks(yticks)
# can use python string formatting and list comprehensions
aax.set_yticklabels(['${0:5.1f}$'.format(y) for y in yticks], fontsize=18);     

Graph Graph

There are a number of more advanced methods for controlling major and minor tick placement in matplotlib figures, such as automatic placement according to different policies. See
http://matplotlib.org/api/ticker_api.html
for details.

Scientific Notation

With large numbers on axes, it is often better use scientific notation.

fig, ax = plt.subplots(1, 1)

ax.plot(x, x**2, x, np.exp(x))
ax.set_title("scientific notation")

ax.set_yticks([0, 50, 100, 150])

from matplotlib import ticker
formatter = ticker.ScalarFormatter(useMathText=True)
formatter.set_scientific(True)
formatter.set_powerlimits((-1,1))
ax.yaxis.set_major_formatter(formatter)     

Graph Graph

Axis Number and Label Spacing

import matplotlib   # to make style changes i.e. rcParams
# distance between x and y axis and the numbers on the axes
matplotlib.rcParams['xtick.major.pad'] = 5
matplotlib.rcParams['ytick.major.pad'] = 5

fig, ax = plt.subplots(1, 1)

ax.plot(x, x**2, x, np.exp(x))
ax.set_yticks([0, 50, 100, 150])

ax.set_title("label and axis spacing")

# padding between axis label and axis numbers
ax.xaxis.labelpad = 5
ax.yaxis.labelpad = 5

ax.set_xlabel("x")
ax.set_ylabel("y");

Graph Graph

# restore defaults for axis number padding
matplotlib.rcParams['xtick.major.pad'] = 3
matplotlib.rcParams['ytick.major.pad'] = 3

Axis Position Adjustment

Unfortunately, when saving figures the labels are sometimes clipped, and it can be necessary to adjust the positions of axes a little bit. This can be done using subplots_adjust.

fig, ax = plt.subplots(1, 1)

ax.plot(x, x**2, x, np.exp(x))
ax.set_yticks([0, 50, 100, 150])

ax.set_title("title")
ax.set_xlabel("x")
ax.set_ylabel("y")

fig.subplots_adjust(left=0.15, right=.9, bottom=0.1, top=0.9);

Graph Graph

Axis Grid

With the grid method in the axis object, we can turn on and off grid lines. We can also customize the appearance of the grid lines using the same keyword arguments as the plot function.

fig, axes = plt.subplots(1,2,figsize=(10,3))

# default grid appearance
axes[0].plot(x,x**2, x, x**3, lw=2)
axes[0].grid(True)

# customize grid appearance
axes[1].plot(x, x**2, x, x**3, lw=2)
axes[1].grid(color='b', alpha=0.25, linestyle='dashed', linewidth=0.5)

Graph Graph

Axis Spines

We can also change the properties of axis spines.

fig, ax = plt.subplots(figsize=(6,2))

ax.spines['bottom'].set_color('blue')
ax.spines['top'].set_color('blue')

ax.spines['left'].set_color('red')
ax.spines['left'].set_linewidth(2)

# turn off axis spine to the right
ax.spines['right'].set_color("none")
ax.yaxis.tick_left() # only ticks on the left side

Graph Graph

Twin Axes

Sometimes it is useful to have dual x or y axes in a figure; for example, when plotting curves with different units together. Matplotlib supports this with the twinx and twiny functions.

fig, ax1 = plt.subplots()

ax1.plot(x, x**2, lw=2, color="blue")
ax1.set_ylabel(r"area $(m^2)$", fontsize=18, color="blue")
for label in ax1.get_yticklabels():
    label.set_color("blue")

ax2 = ax1.twinx()
ax2.plot(x, x**3, lw=2, color="red")
ax2.set_ylabel(r"volume $(m^3)$", fontsize=18, color="red")
for label in ax2.get_yticklabels():
    label.set_color("red")

Graph Graph

Coordinate Axis (no frame)

As seen from the examples above the default is a coordinate axis framing box. If we want a set of axes centred at \((0,0)\) we can use the spines() method, and the set_position submethod.

fig, ax = plt.subplots()

ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0)) # set position of x spine to y=0

ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))   # set position of y spine to x=0

xx = np.linspace(-0.75, 1., 100)
ax.plot(xx, xx**3);

Graph Graph

Other 2D Plot Styles

In addition to the regular plot method, there are a number of other functions for generating different kind of plots. See the matplotlib plot gallery for a complete list of available plot types:
http://matplotlib.org/gallery.html
Some of the more useful ones are show below.

n = np.array([0,1,2,3,4,5])
fig, axes = plt.subplots(1, 4, figsize=(12,3))

axes[0].scatter(xx, xx + 0.25*np.random.randn(len(xx))) # xx defined above
axes[0].set_title("scatter")

axes[1].step(n, n**2, lw=2)
axes[1].set_title("step")

axes[2].bar(n, n**2, align="center", width=0.5, alpha=0.5)
axes[2].set_title("bar")

axes[3].fill_between(x, x**2, x**3, color="green", alpha=0.5);
axes[3].set_title("fill_between");

Graph Graph

Text Annotation

Annotating text in matplotlib figures can be done using the text function. It supports LaTeX formatting just like axis label texts and titles.

xx = np.linspace(-0.75, 1., 100)
fig, ax = plt.subplots()

ax.plot(xx, xx**2, xx, xx**3)

# center coordinate axes
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data',0)) # set position of x spine to y=0
ax.spines['left'].set_position(('data',0)) # set position of y spine to x=0

ax.text(0.1, 0.2, r"$y=x^2$", fontsize=20, color="tab:blue")
ax.text(0.65, 0.1, r"$y=x^3$", fontsize=20, color="tab:orange");

Graph Graph

Figures with Multiple Subplots

Axes can be added to a matplotlib Figure canvas manually using fig.add_axes or using a sub-figure layout manager such as subplots, subplot2grid, or gridspec.

Subplots

fig, ax = plt.subplots(2, 3)
fig.tight_layout()

Graph Graph

subplot2grid

fig = plt.figure()
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
ax1.text(0.5,0.5,'subplot 1',ha='center',va='center',size=14,alpha=.5)
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
ax2.text(0.5,0.5,'subplot 2',ha='center',va='center',size=14,alpha=.5)
ax3 = plt.subplot2grid((3,3), (1,2), rowspan=2)
ax3.text(0.5,0.5,'subplot 3',ha='center',va='center',size=14,alpha=.5)
ax4 = plt.subplot2grid((3,3), (2,0))
ax4.text(0.5,0.5,'subplot 4',ha='center',va='center',size=14,alpha=.5)
ax5 = plt.subplot2grid((3,3), (2,1))
ax5.text(0.5,0.5,'subplot 5',ha='center',va='center',size=14,alpha=.5)
fig.tight_layout()
fig.tight_layout()

Graph Graph

gridspec

import matplotlib.gridspec as gridspec
fig = plt.figure()

gs = gridspec.GridSpec(2, 3, height_ratios=[2,1], width_ratios=[1,2,1])
for g in gs:
    ax = fig.add_subplot(g)

fig.tight_layout()

Graph Graph

Another example.

import matplotlib.gridspec as gridspec

G = gridspec.GridSpec(3, 3)

axes_1 = plt.subplot(G[0, :])
axes_1.set_xticks([]), axes_1.set_yticks([])
axes_1.text(0.5,0.5, 'Axes 1',ha='center',va='center',size=24,alpha=.5)

axes_2 = plt.subplot(G[1,:-1])
axes_2.set_xticks([]), axes_2.set_yticks([])
axes_2.text(0.5,0.5, 'Axes 2',ha='center',va='center',size=24,alpha=.5)

axes_3 = plt.subplot(G[1:, -1])
axes_3.set_xticks([]), axes_3.set_yticks([])
axes_3.text(0.5,0.5, 'Axes 3',ha='center',va='center',size=24,alpha=.5)

axes_4 = plt.subplot(G[-1,0])
axes_4.set_xticks([]), axes_4.set_yticks([])
axes_4.text(0.5,0.5, 'Axes 4',ha='center',va='center',size=24,alpha=.5)

axes_5 = plt.subplot(G[-1,-2])
axes_5.set_xticks([]), axes_5.set_yticks([])
axes_5.text(0.5,0.5, 'Axes 5',ha='center',va='center',size=24,alpha=.5)

Graph Graph

add_axes

Manually adding axes with add_axes is useful for adding insets to figures

fig, ax = plt.subplots()

ax.plot(xx, xx**2, xx, xx**3)
fig.tight_layout()

# inset
inset_ax = fig.add_axes([0.2, 0.55, 0.35, 0.35]) # X, Y, width, height

inset_ax.plot(xx, xx**2, xx, xx**3)
inset_ax.set_title('zoom near origin')

# set axis range
inset_ax.set_xlim(-.2, .2)
inset_ax.set_ylim(-.005, .01)

# set axis tick locations
inset_ax.set_yticks([0, 0.005, 0.01])
inset_ax.set_xticks([-0.1,0,.1]);

Graph Graph