import numpy as np
import sympy
import matplotlib as mpl
import matplotlib.pyplot as plt
'font.size'] = 12.0 mpl.rcParams[
Appendix K — Matplotlib: Plotting and Visualization
Matplotlib
is a Python library for publication-quality 2D and 3D graphics, with support for a variety of different output formatsMore information about
matplotlib
is available at the project’s web site https://matplotlib.orgThis gallery is a great source of inspiration for visualization ideas, and I highly recommend exploring
matplotlib
by browsing this gallery
K.1 Importing matplotlib
print('matplotlib:', mpl.__version__)
print('numpy: ', np.__version__)
print('sympy: ', sympy.__version__)
matplotlib: 3.8.0
numpy: 1.23.5
sympy: 1.12
K.2 Getting started
= np.linspace(-5, 2, 100)
x
= x**3 +5*x**2 +10
y1 = 3*x**2 +10*x
y2 = 6*x +10
y3
#---------------------------------------
= plt.subplots(figsize=(6, 4))
fig, ax
="blue", label="$y(x)$")
ax.plot(x, y1, color="red", label="$y'(x)$")
ax.plot(x, y2, color="green", label="$y''(x)$")
ax.plot(x, y3, color
"$x$")
ax.set_xlabel("$y$")
ax.set_ylabel(
ax.legend()
plt.show()
= plt.subplots(figsize=(6, 4))
fig, ax
=1.5, color="blue", label=r"$y(x)$")
ax.plot(x, y1, lw=1.5, color="red", label=r"$y'(x)$")
ax.plot(x, y2, lw=1.5, color="green", label=r"$y''(x)$")
ax.plot(x, y3, lw
=0.5, color="black")
ax.plot(x, np.zeros_like(x), lw-3.33], [(-3.33)**3 + 5*(-3.33)**2 + 10],
ax.plot([=0.5, marker='o', color="blue")
lw0], [10], lw=0.5, marker='o', color="blue")
ax.plot([-3.33, -3.33], [0, (-3.33)**3 + 5*(-3.33)**2 + 10],
ax.plot([='--', lw=0.5, color="black")
ls0, 0], [0, 10], ls='--', lw=0.5, color="black")
ax.plot([
-5, 2.5])
ax.set_xlim([-5, -2.5, 0, 2.5])
ax.set_xticks([-20, 40)
ax.set_ylim(-20, -10, 0, 10, 20, 30, 40])
ax.set_yticks([
"$x$", fontsize=14)
ax.set_xlabel("$y$", fontsize=14)
ax.set_ylabel(
=2, ncol=3, fontsize=14, frameon=False)
ax.legend(loc
plt.show()
K.3 Figure
= np.linspace(-2, 2, 1000)
x
= np.cos(40*x)
y1 = np.exp(-x**2)
y2
#---------------------------------------
# the width and height of the figure canvas in inches
= plt.figure(figsize=(6, 3), facecolor="#f1f1f1")
fig
# axes coordinates as fractions of
# the canvas width and height
= 0.1, 0.1, 0.8, 0.8
left, bottom, width, height = fig.add_axes((left, bottom, width, height),
ax ="#e1e1e1")
facecolor
*y2)
ax.plot(x, y1 'g')
ax.plot(x, y2, -y2, 'g')
ax.plot(x,
"x")
ax.set_xlabel("y")
ax.set_ylabel(
plt.show()
"./figures/matplotlib_savefig.png", dpi=100, facecolor="#f1f1f1")
fig.savefig("./figures/matplotlib_savefig.pdf", dpi=300, facecolor="#f1f1f1") fig.savefig(
K.4 Axes
Matplotlib
provides several differentAxes
layout managers, which create and placeAxes
instances within afigure
canvas following different strategiesTo facilitate the forthcoming examples, \(\,\)we here briefly look at one of these layout managers:
plt.subplots
Earlier in this appendix, \(\,\)we already used this function to conveniently generate new
Figure
andAxes
objects in one function callHowever, \(\,\)the
plt.subplots
function is also capable of filling a figure with a grid ofAxes
instances, which is specified using the first and the second arguments, or alternatively with thenrows
andncols
arguments, which, as the names implies, creates a grid ofAxes
objects, \(\,\)with the given number of rows and columns= plt.subplots(nrows=3, ncols=2) fig, axes
Here, the function
plt.subplots
returns a tuple(fig, axes)
, wherefig
is afigure
andaxes
is anumpy
array of size(ncols, nrows)
, \(\,\)in which each element is anAxes
instance that has been appropriately placed in the correspondingfigure
canvas. \(\,\)At this point we can also specify that columns and/or rows should share x and y axes, using thesharex
andsharey
arguments, which can be set toTrue
orFalse
The
plt.subplots
function also takes two special keyword argumentsfig_kw
andsubplot_kw
, which are dictionaries with keyword arguments that are used when creating theFigure
andAxes
instances, respectively. This allows us to set and retain full control of the properties of theFigure
andAxes
objects withplt.subplots
, \(\,\)a similar way is possible when directly usingplt.figure
and theadd_axes
method
K.5 Plot types
Matplotlib
implements many types of plotting techniques as methods of theAxes
objectFor details, see Matplotlib’s plot types
def hide_labels(fig, ax, fignum):
ax.set_xticks([])
ax.set_yticks([])
'none')
ax.xaxis.set_ticks_position('none')
ax.yaxis.set_ticks_position(
'tight')
ax.axis(
+= 1
fignum #fig.savefig(f"./figures/plot_types_{fignum}.pdf")
= np.linspace(-3, 3, 25)
x = x**3 +3*x**2 +10
y1 = -1.5*x**3 +10*x**2 -15 y2
= plt.subplots(figsize=(6, 4))
fig, ax
ax.plot(x, y1)
ax.plot(x, y2)
1) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
ax.step(x, y1)
ax.step(x, y2)
2) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
= 6/50
width
- width/2, y1, width=width, color="blue")
ax.bar(x + width/2, y2, width=width, color="green")
ax.bar(x
3) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
=15, edgecolor="black")
ax.hist(y2, bins=15, edgecolor="black")
ax.hist(y1, bins
4) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
=y1, lw=0.6, fmt='--o', capsize=5)
ax.errorbar(x, y2, yerr
5) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
="black")
ax.fill_between(x, y1, y2, edgecolor
6) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
='b', markerfmt='bs')
ax.stem(x, y1, linefmt='r', markerfmt='ro')
ax.stem(x, y2, linefmt
7) hide_labels(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
= np.linspace(0, 5, 50)
x
-1 +x +0.25*x**2 +2*np.random.rand(len(x)))
ax.scatter(x, +2*np.random.rand(len(x)), color="green")
ax.scatter(x, np.sqrt(x)
8) hide_labels(fig, ax,
= y = np.linspace(-np.pi, np.pi, 16)
x = np.meshgrid(x, y)
X, Y = np.sin(X)
U = np.cos(Y)
V
= plt.subplots(figsize=(5, 5))
fig, ax
ax.quiver(X, Y, U, V)9) hide_labels(fig, ax,
= plt.subplots(figsize=(5, 5))
fig, ax
ax.streamplot(X, Y, U, V)9) hide_labels(fig, ax,
'_mpl-gallery')
plt.style.use(
# make data:
10)
np.random.seed(= np.random.normal((3, 5, 4), (1.25, 1.00, 1.25), (100, 3))
D
# plot
= plt.subplots(figsize=(5, 5))
fig, ax = ax.boxplot(D,
VP =[2, 4, 6],
positions=1.5,
widths=True,
patch_artist=False,
showmeans=False,
showfliers={"color": "white", "linewidth": 0.5},
medianprops={"facecolor": "C0", "edgecolor": "white",
boxprops"linewidth": 0.5},
={"color": "C0", "linewidth": 1.5},
whiskerprops={"color": "C0", "linewidth": 1.5})
capprops
set(xlim=(0, 8), xticks=[],
ax.=(0, 8), yticks=[])
ylim
plt.show()
'_mpl-gallery-nogrid')
plt.style.use(
# make data
= [1, 2, 3, 4]
x = plt.get_cmap('Blues')(np.linspace(0.2, 0.7, len(x)))
colors
# plot
= plt.subplots(figsize=(5, 5))
fig, ax =colors, radius=3, center=(4, 4),
ax.pie(x, colors={"linewidth": 1, "edgecolor": "white"}, frame=True)
wedgeprops
set(xlim=(0, 8), xticks=[],
ax.=(0, 8), yticks=[])
ylim
plt.show()
K.6 Line properties
- In
matplotlib
, \(\,\)we set the line properties with keyword arguments to theplot
methods, such as for exampleplot
,step
,bar
def axes_settings(fig, ax, title, ymax):
ax.set_title(title)0, ymax +1)
ax.set_ylim(
ax.set_xticks([])
ax.set_yticks([])
= np.linspace(-5, 5, 5)
x = np.ones_like(x) y
= plt.subplots(figsize=(6, 4))
fig, ax
# Line width
= [0.5, 1.0, 2.0, 4.0]
linewidths for n, linewidth in enumerate(linewidths):
+ n, color="blue", linewidth=linewidth)
ax.plot(x, y
"linewidth", len(linewidths)) axes_settings(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
# Line style
= ['-', '--', '-.', ':']
linestyles for n, linestyle in enumerate(linestyles):
+ n, color="blue", linestyle=linestyle)
ax.plot(x, y
# Custom dash style
= ax.plot(x, y + len(linestyles), color="red", lw=2)
line, = 5, 2, 10, 2
length1, gap1, length2, gap2
line.set_dashes([length1, gap1, length2, gap2])
"linestyle", len(linestyles) + 1) axes_settings(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
# Marker types
= ['+', 'o', '*', 's', '.', '1', '2', '3', '4']
markers for n, marker in enumerate(markers):
+ n, color="blue", lw=0, marker=marker)
ax.plot(x, y
"markers", len(markers)) axes_settings(fig, ax,
= plt.subplots(figsize=(6, 4))
fig, ax
# Marker size and color
= [(4, "white"), (8, "red"), (12, "yellow"), (16, "lightgreen")]
markersizeandcolors for n, (markersize, markercolor) in enumerate(markersizeandcolors):
+ n, color="blue", lw=1, ls='-',
ax.plot(x, y ='o',
marker=markersize,
markersize=markercolor,
markerfacecolor=2)
markeredgewidth
"marker size/color", len(markersizeandcolors)) axes_settings(fig, ax,
# a symboloc variable for x, and a numerical array with specific values of x
= sympy.Symbol("x")
sym_x = np.linspace(-2*np.pi, 2*np.pi, 100)
x
def sin_expansion(x, n):
"""
Evaluate the n-th order Taylor series expansion of sin(x)
for numerical values in the numpy array x
"""
return sympy.lambdify(sym_x, sympy.sin(sym_x).series(n=n).removeO(), 'numpy')(x)
= plt.subplots(figsize=(6, 4))
fig, ax
=4, color="red", label='exact')
ax.plot(x, np.sin(x), lw
= ["blue", "black"]
colors =[':', '-.', '--']
linestyles
for idx, n in enumerate(range(2, 13, 2)):
ax.plot(x, sin_expansion(x, n), =colors[idx //3],
color=linestyles[idx %3],
ls=3,
lw=f'O({n})')
label
-1.5*np.pi, 1.5*np.pi)
ax.set_xlim(-1.25, 1.25)
ax.set_ylim(
# place a legend outside of the Axes
=(1.02, 1), loc=2, borderaxespad=0.0) ax.legend(bbox_to_anchor
= np.random.randn(200, 2) *np.array([3, 1])
data1 = np.random.randn(200, 2) *np.array([1, 3])
data2
= plt.subplots(2, 1, figsize=(6, 8), sharey=True)
fig, axes
0].scatter(data1[:, 0], data1[:, 1], color="g", marker="s", s=30, alpha=0.5)
axes[0].scatter(data2[:, 0], data2[:, 1], color="b", marker="o", s=30, alpha=0.5)
axes[
1].hist([data1[:, 1], data2[:, 1]],
axes[=15,
bins=["g", "b"],
color=0.5,
alpha='horizontal')
orientation
plt.show()
K.7 Legends
See
help(plt.legend)
for details. \(\,\)Theloc
argument allows us to specify where in theAxes
area thelegend
is to be added:loc=1
for upper right corner,loc=2
for upper left corner,loc=3
for the lower-left corner, andloc=4
for lower right cornerIn the example of the previous section, \(\,\)we used the
bbox_to_anchor
, \(\,\)which helps thelegend
be placed at an arbitrary location within thefigure
canvas. Thebbox_to_anchor
argument takes the value of a tuple on the form(x, y)
, \(~\)wherex
andy
are the canvas coordinates within theAxes
object. That is, \(\,\)the point(0, 0)
corresponds to the lower-left corner, and(1, 1)
corresponds to the upper right corner. \(\,\)Note thatx
andy
can be smaller than0
and larger than1
, in this case, which indicates that thelegend
is to be placed outside theAxes
area, \(\,\)as was used in the previous sectionBy default, all lines in the
legend
are shown in a vertical arrangement. Using thencols
argument, it is possible to split thelegend
labels into multiple columns
= np.linspace(0, 1, 100)
x
= plt.subplots(4, 1, figsize=(6, 12), sharex=True)
fig, axes
for n in range(4):
="$y(x) = x$")
axes[n].plot(x, x, label+x**2, label="$y(x) = x + x^2$")
axes[n].plot(x, x =n + 1)
axes[n].legend(locf'legend: loc={n + 1}') axes[n].set_title(
= np.linspace(-1, 1, 100)
x
def linear_eqn(x, slope):
return slope *x
= plt.subplots(figsize=(6, 3))
fig, ax
= ['blue', 'green', 'red', 'cyan',
colors 'magenta', 'yellow', 'black', 'orange']
for slope in range(1, 9):
ax.plot(x,
linear_eqn(x, slope), =colors[slope -1],
color=f"$y(x)={slope:d}x$")
label
-1, 1)
ax.set_xlim(-8, 8)
ax.set_ylim(
='x', pad=10)
ax.tick_params(axis
=(-0.01, 1.05), ncol=4, loc=3, borderaxespad=0.0) ax.legend(bbox_to_anchor
K.8 Text formatting and annotations
Matplotlib
provides several ways of configuring fonts properties. \(\,\)The default values can be set in thematplotlib
resource file. \(\,\)To display where the currently activematplotlib
file is loaded from, \(\,\)one can do the following:mpl.matplotlib_fname()
And session-wide configuration can be set in the
mpl.rcParams
dictionary: \(~\)for example,'font.size'] = 12.0 mpl.rcParams[
Try
print(mpl.rcParams)
to get a list of possible configuration parameters and their current valuesMatplotlib
provides excellent support for LaTeX markup within its text labels: Any text label inmatplotlib
can include LaTeX math by enclosing it within$
signs: \(\,\) for example'Regular text: $f(x)=1-x^2$'
By default, \(\,\)
matplotlib
uses an internal LaTeX rendering, \(\,\)which supports a subset of LaTeX language. However, by setting the configuration parametermpl.rcParams['text.usetex']=True
, \(~\)it is also possible to use an external full-featured LaTeX engineWhen embedding LaTeX code in strings there is a common stumbling block: Python uses
\
as escape character, \(\,\)while in LaTeX it is used to denote the start of commands. \(\,\)To prevent the Python interpreter from escaping characters in strings containing LaTeX expressions, \(\,\)it is convenient to use raw strings, \(\,\)which are literal string expressions that are prepended with anr
, \(\,\)for example:r"$\int f(x) dx$"
andr'$x_{\rm A}$'
= np.linspace(-20, 20, 100)
x = np.sin(x) /x
y
= plt.subplots(figsize=(6, 4))
fig, ax
ax.plot(x, y)
"x label")
ax.set_xlabel("y label")
ax.set_ylabel(
for label in ax.get_xticklabels() +ax.get_yticklabels():
45) label.set_rotation(
= plt.subplots(figsize=(6, 3))
fig, ax
ax.set_xticks([])
ax.set_yticks([])-0.50, 3.50)
ax.set_xlim(-0.05, 0.25)
ax.set_ylim(0)
ax.axhline(
# text label
0, 0.1, "Text label", fontsize=14, family="serif")
ax.text(
# annotation
1, 0, "o")
ax.plot("Annotation", fontsize=14, family="serif",
ax.annotate(=(1, 0),
xy="data",
xycoords=(20, 50),
xytext="offset points",
textcoords=dict(arrowstyle="->", connectionstyle="arc3, rad=.5"))
arrowprops
# equation
2, 0.1,
ax.text(r"Equation: $i\hbar\partial_t \Psi = \hat{H}\Psi$",
=14, family="serif")
fontsize
plt.show()
'font', family='NanumGothic')
mpl.rc('axes.unicode_minus'] = False mpl.rcParams[
= 1000 +np.random.randint(-100, 100, 50).cumsum()
data
= plt.subplots(figsize=(6, 4))
fig, ax
range(50), data, 'r')
ax.plot(
'시간대별 가격 추이')
ax.set_title('주식 가격, [원]')
ax.set_ylabel('시간, [분]')
ax.set_xlabel( plt.show()
'font', family='serif')
mpl.rc('axes.unicode_minus'] = True mpl.rcParams[
K.9 Axis properties
K.9.1 Axis labels and titles
= np.linspace(0, 50, 500)
x = np.sin(x) *np.exp(-x /10)
y
= plt.subplots(figsize=(6, 2), subplot_kw={'facecolor': "#ebf5ff"})
fig, ax
=2)
ax.plot(x, y, lw
0, 50])
ax.set_xlim([-1.0, 1.0])
ax.set_ylim([
"x", labelpad=5, fontsize=14, fontname='serif', color='blue')
ax.set_xlabel("f(x)", labelpad=5, fontsize=14, fontname='serif', color='blue')
ax.set_ylabel(
"Axis labels and Title example",
ax.set_title(=14, fontname='serif', color='blue', loc='center')
fontsize
plt.show()
K.9.2 Axis range
= np.linspace(0, 30, 500)
x = np.sin(x) *np.exp(-x /10)
y
= plt.subplots(4, 1, figsize=(6, 12),
fig, axes ={'facecolor': '#ebf5ff'})
subplot_kw
0].plot(x, y, lw=2)
axes[0].set_xlim(-5, 35)
axes[0].set_ylim(-1, 1)
axes[0].set_title("set_[x/y]lim")
axes[
1].plot(x, y, lw=2)
axes[1].axis('tight')
axes[1].set_title("axis('tight')")
axes[
2].plot(x, y, lw=2)
axes[2].axis('equal')
axes[2].set_title("axis('equal')")
axes[
3].plot(x, y, lw=2)
axes[3].autoscale(True)
axes[3].set_title("autoscale(True)")
axes[
plt.show()
K.9.3 Axis ticks, tick labels, and grids
\(~\)
= np.linspace(-2*np.pi, 2*np.pi, 500)
x = np.sin(x) *np.exp(-x**2/20)
y
= plt.subplots(2, 1, figsize=(6, 8))
fig, axes
0].plot(x, y, lw=2)
axes[0].set_title("default ticks")
axes[0].tick_params(which='both', direction='in')
axes[
1].plot(x, y, lw=2)
axes[1].set_title("set_[x/y]ticks")
axes[1].set_xticks([-5, 0, 5])
axes[1].set_yticks([-1, 0, 1])
axes[1].tick_params(which='both', direction='in') axes[
= plt.subplots(2, 1, figsize=(6, 8))
fig, axes
0].plot(x, y, lw=2)
axes[0].set_title("set_major/minor_locator")
axes[0].xaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
axes[0].xaxis.set_minor_locator(mpl.ticker.MaxNLocator(8))
axes[0].yaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
axes[0].yaxis.set_minor_locator(mpl.ticker.MaxNLocator(8))
axes[0].tick_params(which='both', direction='in')
axes[
1].plot(x, y, lw=2)
axes[1].set_title("set_[x/y]ticklabels")
axes[1].set_xticks([-2*np.pi, -np.pi, 0, np.pi, 2*np.pi])
axes[1].set_xticklabels(['$-2\pi$', '$-\pi$', '$0$', '$\pi$', '$2\pi$'])
axes[1].xaxis.set_minor_locator(
axes[-3*np.pi/2, -np.pi/2, 0, np.pi/2, 3*np.pi/2]))
mpl.ticker.FixedLocator([1].set_yticks([-1, 0, 1])
axes[1].yaxis.set_minor_locator(mpl.ticker.MaxNLocator(8))
axes[1].tick_params(which='both', direction='in') axes[
= plt.subplots(3, 1, figsize=(6, 12))
fig, axes
for ax in axes:
=2)
ax.plot(x, y, lw4))
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5))
ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.25))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(
0].set_title("default grid")
axes[0].grid()
axes[
1].set_title("major/minor grid")
axes[1].grid(color="blue", which="both", ls=':', lw=0.5)
axes[
2].set_title("individual x/y major/minor grid")
axes[2].grid(color="gray", which="major", axis='x', ls='-', lw=0.5)
axes[2].grid(color="gray", which="minor", axis='x', ls=':', lw=0.25)
axes[2].grid(color="gray", which="major", axis='y', ls='-', lw=0.5) axes[
= np.linspace(0, 1e5, 100)
x = x**2
y
= plt.subplots(2, 1, figsize=(6, 8))
fig, axes
0].plot(x, y, 'b.')
axes[0].set_title("default labels", loc='right')
axes[
1].plot(x, y, 'b')
axes[1].set_title("scientific notation labels", loc='right')
axes[
= mpl.ticker.ScalarFormatter(useMathText=True)
formatter -1, 2))
formatter.set_powerlimits((
1].xaxis.set_major_formatter(formatter)
axes[1].yaxis.set_major_formatter(formatter) axes[
K.9.4 Log lots
= np.linspace(0, 1e3, 100)
x = x**3, x**4
y1, y2
= plt.subplots(3, 1, figsize=(6, 12))
fig, axes
0].set_title('loglog')
axes[0].loglog(x, y1, 'b', x, y2, 'r')
axes[
1].set_title('semilogy')
axes[1].semilogy(x, y1, 'b', x, y2, 'r')
axes[
2].set_title('plot set_[x/y]scale')
axes[2].plot(x, y1, 'b', x, y2, 'r')
axes[2].set_xscale('log')
axes[2].set_yscale('log') axes[
K.9.5 Twin axes
= np.linspace(0, 5, 100)
radius = 4 *np.pi *radius**2 # area
area = (4 *np.pi /3) *radius**3 # volume volume
= plt.subplots(figsize=(6, 4))
ig, ax1
"Surface area and Volume of a sphere", fontsize=16)
ax1.set_title("radius, [m]", fontsize=16)
ax1.set_xlabel(
=2, color="blue")
ax1.plot(radius, area, lwr"Surface area, [$m^2$]", fontsize=16, color="blue")
ax1.set_ylabel(0, 5)
ax1.set_xlim(0, 350)
ax1.set_ylim(
for label in ax1.get_yticklabels():
"blue")
label.set_color(
= ax1.twinx()
ax2 =2, color="red")
ax2.plot(radius, volume, lwr"Volume, [$m^3$]", fontsize=16, color="red")
ax2.set_ylabel(0, 600)
ax2.set_ylim(for label in ax2.get_yticklabels():
"red") label.set_color(
K.9.6 Spines
= np.linspace(-10, 10, 500)
x = np.sin(x) /x
y
= plt.subplots(figsize=(6, 4))
fig, ax
=2)
ax.plot(x, y, lw
-10, -5, 5, 10])
ax.set_xticks([0.5, 1])
ax.set_yticks([
# remove top and right spines
'top'].set_color('none')
ax.spines['right'].set_color('none')
ax.spines[
# set only bottom and left spine ticks
'bottom')
ax.xaxis.set_ticks_position('left')
ax.yaxis.set_ticks_position(
# move bottom and left spines to x = 0 and y = 0
'bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0)) ax.spines[
K.10 Advanced axes layouts
K.10.1 Insets
def f(x):
return 1 /(1 +x**2) +0.1 /(1 +((3 -x) /0.1)**2)
def plot_and_format_axes(ax, x, f, fontsize):
=2)
ax.plot(x, f(x), lw5))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
"$x$", fontsize=fontsize)
ax.set_xlabel("$f(x)$", fontsize=fontsize)
ax.set_ylabel(
for label in ax.get_xticklabels() +ax.get_yticklabels():
label.set_fontsize(fontsize)
='both', direction='in') ax.tick_params(which
= np.linspace(-4, 14, 1000)
x
= plt.figure(figsize=(6.5, 4))
fig
# main graph
= fig.add_axes([0.1, 0.15, 0.8, 0.8], facecolor="#f5f5f5")
ax 12)
plot_and_format_axes(ax, x, f,
= 2.5, 3.5
x0, x1 = np.linspace(x0, x1, 1000)
x
=0.3, color="gray", ls=':')
ax.axvline(x0, ymax=0.3, color="gray", ls=':')
ax.axvline(x1, ymax
# inset
= fig.add_axes([0.5, 0.5, 0.38, 0.42], facecolor='none')
ax1 10) plot_and_format_axes(ax1, x, f,
K.10.2 Subplots
= np.random.randn(100)
x1 = np.random.randn(100)
x2
# squeeze=False, the axes is always a two-dimensional array
= plt.subplots(2, 2, figsize=(7, 7),
fig, axes =True,
sharex=True,
sharey=False)
squeeze
0, 0].set_title("Uncorrelated", fontsize=12)
axes[0, 0].scatter(x1, x2)
axes[
0, 1].set_title("Weakly positively correlated", fontsize=12)
axes[0, 1].scatter(x1, x1 +x2)
axes[
1, 0].set_title("Weakly negatively correlated", fontsize=12)
axes[1, 0].scatter(x1,-x1 +x2)
axes[
1, 1].set_title("Strongly correlated", fontsize=12)
axes[1, 1].scatter(x1, x1 +0.15*x2)
axes[
1, 1].set_xlabel("x")
axes[1, 0].set_xlabel("x")
axes[0, 0].set_ylabel("y")
axes[1, 0].set_ylabel("y")
axes[
=0.1,
plt.subplots_adjust(left=0.95,
right=0.1,
bottom=0.95,
top=0.1,
wspace=0.2) hspace
K.10.3 Subplot2grid
def plot_and_format_axes(ax, ax_number):
0, 6)
ax.set_xlim(0, 6)
ax.set_ylim(
6))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(6))
ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
='both', direction='in', top=True, right=True)
ax.tick_params(which
ax.set_xticklabels([])
ax.set_yticklabels([])3, 3, f'ax{ax_number}',
ax.text(='center',
horizontalalignment='center') verticalalignment
=(6, 6))
plt.figure(figsize
= plt.subplot2grid((3, 3), (0, 0))
ax0 = plt.subplot2grid((3, 3), (0, 1))
ax1 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax2 = plt.subplot2grid((3, 3), (2, 0), colspan=3)
ax3 = plt.subplot2grid((3, 3), (0, 2), rowspan=2)
ax4
= [ax0, ax1, ax2, ax3, ax4]
axes
for i in range(5):
plot_and_format_axes(axes[i], i)
K.10.4 GridSpec
= plt.figure(figsize=(6, 6))
fig
= mpl.gridspec.GridSpec(4, 4)
gs
= fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[1, 1])
ax0, ax1 = fig.add_subplot(gs[2, 2]), fig.add_subplot(gs[3, 3])
ax2, ax3 = fig.add_subplot(gs[0, 1:]), fig.add_subplot(gs[1:, 0])
ax4, ax5 = fig.add_subplot(gs[1, 2:]), fig.add_subplot(gs[2:, 1])
ax6, ax7 = fig.add_subplot(gs[2, 3]), fig.add_subplot(gs[3, 2])
ax8, ax9
= [ax0, ax1, ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9]
axes
for i in range(10):
plot_and_format_axes(axes[i], i)
= plt.figure(figsize=(6, 6))
fig
= mpl.gridspec.GridSpec(2, 2,
gs =[4, 1],
width_ratios=[1, 4],
height_ratios=0.05,
wspace=0.05)
hspace
= fig.add_subplot(gs[1, 0])
ax0 = fig.add_subplot(gs[0, 0])
ax1 = fig.add_subplot(gs[1, 1])
ax2
= [ax0, ax1, ax2]
axes
for i in range(3):
plot_and_format_axes(axes[i], i)
K.11 Colormap plots
= y = np.linspace(-2, 2, 150)
x = np.meshgrid(x, y)
X, Y
= np.sqrt((X +0.5)**2 +(Y +0.5)**2)
R1 = np.sqrt((X +0.5)**2 +(Y -0.5)**2)
R2 = np.sqrt((X -0.5)**2 +(Y +0.5)**2)
R3 = np.sqrt((X -0.5)**2 +(Y -0.5)**2) R4
= plt.subplots(figsize=(7, 6))
fig, ax
= np.sin(10 *R1) /(10 *R1) +np.sin(20 *R4) /(20 *R4)
Z = Z[:-1, :-1]
Z
= ax.pcolor(X, Y, Z, cmap='seismic', vmin=-abs(Z).max(), vmax=abs(Z).max())
p
'tight')
ax.axis(
'x')
ax.set_xlabel('y')
ax.set_ylabel('pcolor')
ax.set_title(
4))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
= fig.colorbar(p, ax=ax)
cb 'z')
cb.set_label(-1, -.5, 0, .5, 1]) cb.set_ticks([
= plt.subplots(figsize=(7, 6))
fig, ax
= 1/R1 -1/R2 -1/R3 +1/R4
Z
= ax.imshow(Z, vmin=-1, vmax=1, cmap=mpl.cm.bwr,
im =[x.min(), x.max(), y.min(), y.max()])
extent'bilinear')
im.set_interpolation(
'tight')
ax.axis(
'x')
ax.set_xlabel('y')
ax.set_ylabel('imshow')
ax.set_title(
4))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
= fig.colorbar(im, ax=ax)
cb 'z')
cb.set_label(-1, -.5, 0, .5, 1]) cb.set_ticks([
= y = np.linspace(0, 1, 75)
x = np.meshgrid(x, y)
X, Y = (-2 *np.cos(2 *np.pi *X) *np.cos(2 *np.pi *Y)
Z -0.7 *np.cos(np.pi -4 *np.pi *X))
= plt.subplots(figsize=(6, 6))
fig, ax
= ax.contour(X, Y, Z, 15, cmap=mpl.cm.RdBu, vmin=-1, vmax=1)
c
'tight')
ax.axis(
'x')
ax.set_xlabel('y')
ax.set_ylabel("contour")
ax.set_title(
4))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(4)) ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
= plt.subplots(figsize=(6, 6))
fig, ax
= ax.contourf(X, Y, Z, 15, cmap=mpl.cm.RdBu, vmin=-1, vmax=1)
c
'tight')
ax.axis(
'x')
ax.set_xlabel('y')
ax.set_ylabel("contourf")
ax.set_title(
4))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
fig.tight_layout()
= y = np.linspace(-10, 10, 150)
x
= np.meshgrid(x, y)
X, Y = np.cos(X) *np.cos(Y) *np.exp(-(X/5)**2 -(Y/5)**2)
Z = Z[:-1, :-1]
P
= mpl.colors.Normalize(-abs(Z).max(), abs(Z).max())
norm
def plot_and_format_axes(fig, ax, p):
'tight')
ax.axis(r"$x$", fontsize=12)
ax.set_xlabel(r"$y$", fontsize=12)
ax.set_ylabel(
4))
ax.xaxis.set_major_locator(mpl.ticker.MaxNLocator(4))
ax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(
='both', direction='in', top=True, right=True)
ax.tick_params(which
= fig.colorbar(p, ax=ax)
cb0 r"$z$", fontsize=14)
cb0.set_label(-1, -0.5, 0, 0.5, 1]) cb0.set_ticks([
= plt.subplots(2, 1, figsize=(7, 12))
fig, axes
= axes[0].pcolor(X, Y, P, norm=norm, cmap=mpl.cm.bwr)
p 0], p)
plot_and_format_axes(fig, axes[
1].contour(X, Y, Z, np.linspace(-1.0, 1.0, 20), norm=norm, cmap=mpl.cm.bwr)
axes[1], p)
plot_and_format_axes(fig, axes[
=0.15) plt.subplots_adjust(hspace
= np.meshgrid(np.linspace(-2, 2, 100), np.linspace(-2, 2, 100))
X, Y
# A low hump with a spike coming out
# needs to have z/colour axis on a log scale so we see both hump and spike
= np.exp(-X**2 -Y**2)
Z1 = np.exp(-(10 *X)**2 -(10 *Y)**2)
Z2 = Z1 +50 *Z2
Z
= plt.subplots(2, 1, figsize=(7, 12))
fig, axes
= axes[0].pcolor(X, Y, Z,
c =mpl.colors.LogNorm(vmin=Z.min(), vmax=Z.max()), cmap='PuBu_r')
norm=axes[0])
fig.colorbar(c, ax
# linear scale only shows the spike
= axes[1].pcolor(X, Y, Z, cmap='PuBu_r')
c =axes[1])
fig.colorbar(c, ax
=0.1) plt.subplots_adjust(hspace
Matplotlib
has a number of built-in colormaps accessible viamatplotlib.colormaps
. To get a list of all registered colormaps, you can do:from matplotlib import colormaps list(colormaps)
K.12 3D plots
In
matplotlib
, \(\,\)drawing 3D graphs requires using a different axes object, namely theAxes3D
object that is available from thempl_toolkits.mplot3d.axes3d
module. \(\,\)We can create a 3D-ware axes instance explicitly using the constructor of theAxes3D
class, \(\,\)by passing aFigure
instance as argument:= Axes3D(fig) ax
Alternatively, \(\,\)we can use the
add_subplot
function with theprojection='3d'
argument:= fig.add_subplot(1, 1, 1, projection='3d') ax
or use
plt.subplots
with thesubplot_kw={'projection':'3d'}
argument:= plt.subplots(1, 1, fig, ax =(6, 6), subplot_kw={'projection':'3d'}) figsize
from mpl_toolkits.mplot3d.axes3d import Axes3D
= y = np.linspace(-3, 3, 74)
x = np.meshgrid(x, y)
X, Y = np.sqrt(X**2 +Y**2)
R = np.sin(4 *R) /R
Z
= mpl.colors.Normalize(-abs(Z).max(), abs(Z).max())
norm
def title_and_labels(ax, title):
ax.set_title(title)
"$x$", labelpad=0.05, fontsize=12)
ax.set_xlabel("$y$", labelpad=0.05, fontsize=12)
ax.set_ylabel("$z$", labelpad=0.05, fontsize=12)
ax.set_zlabel(None, zoom=0.85)
ax.set_box_aspect(='both', pad=0.01) ax.tick_params(axis
= plt.subplots(3, 1, figsize=(6, 16), subplot_kw={'projection': '3d'})
fig, axes
= axes[0].plot_surface(X, Y, Z, rstride=1, cstride=1, lw=0,
p =False, norm=norm, cmap=mpl.cm.Blues)
antialiased0], "plot_surface")
title_and_labels(axes[
1].plot_wireframe(X, Y, Z, rstride=3, cstride=3, color="darkgrey")
axes[1], "plot_wireframe")
title_and_labels(axes[
2].contour(X, Y, Z, zdir='z', offset=0, norm=norm, cmap=mpl.cm.Blues)
axes[2].contour(X, Y, Z, zdir='y', offset=3, norm=norm, cmap=mpl.cm.Blues)
axes[2], "contour")
title_and_labels(axes[
=0.05, right=0.95, bottom=0.1, top=0.95, hspace=0.1) plt.subplots_adjust(left
= plt.subplots(3, 1, figsize=(6, 16), subplot_kw={'projection': '3d'})
fig, axes
= np.linspace(0, 10, 100)
r
= axes[0].plot(np.cos(r), np.sin(r), 6 -r)
p 0], "plot")
title_and_labels(axes[
= axes[1].scatter(np.cos(r), np.sin(r), 6 -r)
p 1], "scatter")
title_and_labels(axes[
= np.linspace(0, 6, 30)
r
= axes[2].bar3d(np.cos(r), np.sin(r), np.zeros_like(r),
p 0.05*np.ones_like(r), 0.05*np.ones_like(r), 6 -r)
2], "bar3d")
title_and_labels(axes[
=0.05, right=0.95, bottom=0.1, top=0.95, hspace=0.1) plt.subplots_adjust(left