Matplotlib
Matplotlib is the "grandfather" library of data visualization with Python. It was created by John Hunter. He created it to try to replicate MatLab's (another programming language) plotting capabilities in Python. So if you happen to be familiar with matlab, matplotlib will feel natural to you.
It is an excellent 2D and 3D graphics library for generating scientific figures.
Some of the major Pros of Matplotlib are:
Generally easy to get started for simple plots
Support for custom labels and texts
Great control of every element in a figure
High-quality output in many formats
Very customizable in general
Matplotlib allows you to create reproducible figures programmatically. Explore the official Matplotlib web page: http://matplotlib.org/
Installation
You'll need to install matplotlib first with either:
conda install matplotlib
import matplotlib.pyplot as pet
%matplotlib inline
That line is only for jupyter notebooks, if you are using another editor, you'll use: plt.show() at
the end of all your plotting commands to have the figure pop up in another window.
import numpy as np
x = np.linspace(0, 5, 11)
y = x ** 2
Basic Matplotlib Commands
We can create a very simple line plot using the following ( I encourage you to pause and use Shift+Tab along the way to check out the document strings for the functions we are using).
plt.plot(x, y, 'r') # 'r' is the color red
plt.xlabel('X Axis Title Here')
plt.ylabel('Y Axis Title Here')
plt.title('String Title Here')
plt.show()
Introduction to the Object Oriented Method
The main idea in using the more formal Object Oriented method is to create figure
objects and then just call methods or attributes off of that object. This approach is nicer when
dealing with a canvas that has multiple plots on it.
To begin we create a figure instance. Then we can add axes to that figure:
# Create Figure (empty canvas)
fig = plt.figure()
# Add set of axes to figure
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1)
# Plot on that set of axes
axes.plot(x, y, 'b')
axes.set_xlabel('Set X Label') # Notice the use of set_ to begin methods
axes.set_ylabel('Set y Label')
axes.set_title('Set Title')
Code is a little more complicated, but the advantage is that we now have full control of where
the plot axes are placed, and we can easily add more than one axis to the figure:
# Creates blank canvas
fig = plt.figure()
axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # inset axes
# Larger Figure Axes 1
axes1.plot(x, y, 'b')
axes1.set_xlabel('X_label_axes2')
axes1.set_ylabel('Y_label_axes2')
axes1.set_title('Axes 2 Title')
# Insert Figure Axes 2
axes2.plot(y, x, 'r')
axes2.set_xlabel('X_label_axes2')
axes2.set_ylabel('Y_label_axes2')
axes2.set_title('Axes 2 Title');
subplots()¶
The plt.subplots() object will act as a more automatic axis manager.
Basic use cases:
# Use similar to plt.figure() except use tuple unpacking to grab fig and axes
fig, axes = plt.subplots()
# Now use the axes object to add stuff to plot
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title');
This will draw a figure as similar image shown above
# Empty canvas of 1 by 2 subplots
fig, axes = plt.subplots(nrows=1, ncols=2)
#Here axes is an array of 2
for ax in axes:
ax.plot(x, y, 'b')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
A common issue with matplolib is overlapping subplots or figures. We ca use **fig.tight_layout()**
or **plt.tight_layout()** method, which automatically adjusts the positions of the axes on the figure
canvas so that there is no overlapping content:
Figure size, aspect ratio and DPI
Matplotlib allows the aspect ratio, DPI and figure size to be specified when
the Figure object is created. You can use the figsize and dpi keyword arguments.
figsize is a tuple of the width and height of the figure in inches
dpi is the dots-per-inch (pixel per inch)
Saving figures
Matplotlib can generate high-quality output in a number formats, including PNG, JPG, EPS, SVG,
PGF and PDF.
To save a figure to a file we can use the savefig method in the Figure class:
fig.savefig("filename.png") or fig.savefig("filename.png", dpi=200)
Legends, labels and titles
Figure titles
A title can be added to each axis instance in a figure. To set the title, use the set_title method in
the axes instance:
ax.set_title("title");
Axis labels
Similarly, with the methods set_xlabel and set_ylabel, we can set the labels of the X and Y axes:
ax.set_xlabel("x")
ax.set_ylabel("y");
Legends
You can use the label="label text" keyword argument when plots or other objects are added to the
figure, and then using the legend method without arguments to add the legend to the figure
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.plot(x, x**2, label="x**2")
ax.plot(x, x**3, label="x**3")
ax.legend()
ax.legend(loc=0) # let matplotlib decide the optimal location
ax.legend(loc=1) # upper right corner
ax.legend(loc=2) # upper left corner
ax.legend(loc=3) # lower left corner
ax.legend(loc=4) # lower right corner
Setting colors, linewidths, linotypes
Matplotlib gives you a lot of options for customizing colors, linewidths, and linotypes.
With matplotlib, we can define the colors of lines and other graphical elements in a number of ways.
First of all, we can use the MATLAB-like syntax where 'b'means blue, 'g' means green, etc.
The MATLAB API for selecting line styles are also supported: where, for example, 'b.-' means a blue line
with dots
# MATLAB style line color and style
fig, ax = plt.subplots()
ax.plot(x, x**2, 'b.-') # blue line with dots
ax.plot(x, x**3, 'g--') # green dashed line
We can also define colors by their names or RGB hex codes and optionally provide an alpha value
using the color and alpha keyword arguments. Alpha indicates opacity.
fig, ax = plt.subplots()
ax.plot(x, x+1, color="blue", alpha=0.5) # half-transparant
ax.plot(x, x+2, color="#8B008B") # RGB hex code
ax.plot(x, x+3, color="#FF8C00") # RGB hex code
Line and marker styles
To change the line width, we can use the linewidth or lw keyword argument. The line style can
be selected using the linestyle or ls keyword arguments:
fig, ax = plt.subplots(figsize=(12,6))
ax.plot(x, x+1, color="red", linewidth=0.25)
ax.plot(x, x+2, color="red", linewidth=0.50)
ax.plot(x, x+3, color="red", linewidth=1.00)
ax.plot(x, x+4, color="red", linewidth=2.00)
# possible linestype options ‘-‘, ‘–’, ‘-.’, ‘:’, ‘steps’
ax.plot(x, x+5, color="green", lw=3, linestyle='-')
ax.plot(x, x+6, color="green", lw=3, ls='-.')
ax.plot(x, x+7, color="green", lw=3, ls=':')
# custom dash
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10]) # format: line length, space length, ...
# possible marker symbols: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
ax.plot(x, x+ 9, color="blue", lw=3, ls='-', marker='+')
ax.plot(x, x+10, color="blue", lw=3, ls='--', marker='o')
ax.plot(x, x+11, color="blue", lw=3, ls='-', marker='s')
ax.plot(x, x+12, color="blue", lw=3, ls='--', marker='1')
# marker size and color
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+16, color="purple", lw=1, ls='-', marker='s', markersize=8,
markerfacecolor="yellow", markeredgewidth=3, markeredgecolor="green");
Control over axis appearance
controlling axis sizing properties in a matplotlib figure
Plot range
We can configure the ranges of the axes using the set_ylim and set_xlim methods in the axis
object, or axis('tight') for automatically getting "tightly fitted" axes ranges:
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
axes[0].plot(x, x**2, x, x**3)
axes[0].set_title("default axes ranges")
axes[1].plot(x, x**2, x, x**3)
axes[1].axis('tight')
axes[1].set_title("tight axes")
axes[2].plot(x, x**2, x, x**3)
axes[2].set_ylim([0, 60])
axes[2].set_xlim([2, 5])
axes[2].set_title("custom axes range");
Special Plot Types
There are many specialized plots we can create, such as barplots, histograms, scatter plots, and
much more. Most of these type of plots we will actually create using seaborn, a statistical plotting
library for Python. But here are a few examples of these type of plots:
plt.scatter(x,y)
Histogram
from random import sample
data = sample(range(1, 1000), 100)
plt.hist(data)
data = [np.random.normal(0, std, 100) for std in range(1, 4)]
# rectangular box plot
plt.boxplot(data,vert=True,patch_artist=True);
Further reading
http://www.matplotlib.org - The project web page for matplotlib.
https://github.com/matplotlib/matplotlib - The source code for matplotlib.
http://matplotlib.org/gallery.html - A large gallery showcaseing various types of plots
matplotlib can create. Highly recommended!
http://www.loria.fr/~rougier/teaching/matplotlib - A good matplotlib tutorial.
http://scipy-lectures.github.io/matplotlib/matplotlib.html - Another good matplotlib reference.
Advanced Matplotlib Concepts Lecture
Logarithmic scale
It is also 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 seperately 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))
axes[0].plot(x, x**2, x, np.exp(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)");
Placement of ticks and custom tick labels
We can explicitly determine where we want the axis ticks with set_xticks and set_ticks,
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])
ax.set_xticklabels([r'$\alpha$', r'$\beta$', r'$\gamma$', r'$\delta$', r'$\epsilon$'], fontsize=18)
yticks = [0, 50, 100, 150]
ax.set_yticks(yticks)
ax.set_yticklabels(["$%.1f$" % y for y in yticks], fontsize=18); # use LaTeX formatted labels
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.
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)
Axis number and axis label spacing
# 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");
# restore defaults
matplotlib.rcParams['xtick.major.pad'] = 3
matplotlib.rcParams['ytick.major.pad'] = 3
Axis position adjustments
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);
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)
# custom grid appearance
axes[1].plot(x, x**2, x, x**3, lw=2)
axes[1].grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
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
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")
Axes where x and y is zero
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 x=0
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0)) # set position of y spine to y=0
xx = np.linspace(-0.75, 1., 100)
ax.plot(xx, xx**3);
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)))
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");
18.png
Figures with multiple subplots and insets
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 grid spec:
subplots
fig, ax = plt.subplots(2, 3)
fig.tight_layout()
subplot2grid
fig = plt.figure()
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
ax3 = plt.subplot2grid((3,3), (1,2), rowspan=2)
ax4 = plt.subplot2grid((3,3), (2,0))
ax5 = plt.subplot2grid((3,3), (2,1))
fig.tight_layout()
gridspec
import matplotlib.gridspec as grid spec
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()
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]);
3D figures
o use 3D graphics in matplotlib, we first need to create an instance of the Axes3D class. 3D axes can
be added to a matplotlib figure canvas in exactly the same way as 2D axes; or, more conveniently,
by passing a projection='3d' keyword argument to the add_axes or add_subplot methods.
from mpl_toolkits.mplot3d.axes3d import Axes3D
Surface plots
fig = plt.figure(figsize=(14,6))
# `ax` is a 3D-aware axis instance because of the projection='3d' keyword argument to add_subplot
ax = fig.add_subplot(1, 2, 1, projection='3d')
p = ax.plot_surface(X, Y, Z, rstride=4, cstride=4, linewidth=0)
# surface_plot with color grading and color bar
ax = fig.add_subplot(1, 2, 2, projection='3d')
p = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False)
cb = fig.colorbar(p, shrink=0.5)
19.png
Wire-frame plot
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1, projection='3d')
p = ax.plot_wireframe(X, Y, Z, rstride=4, cstride=4)
21.png
Coutour plots with projections
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1,1,1, projection='3d')
ax.plot_surface(X, Y, Z, rstride=4, cstride=4, alpha=0.25)
cset = ax.contour(X, Y, Z, zdir='z', offset=-np.pi, cmap=matplotlib.cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='x', offset=-np.pi, cmap=matplotlib.cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='y', offset=3*np.pi, cmap=matplotlib.cm.coolwarm)
ax.set_xlim3d(-np.pi, 2*np.pi);
ax.set_ylim3d(0, 3*np.pi);
ax.set_zlim3d(-np.pi, 2*np.pi);
22.png
Further reading¶
http://www.matplotlib.org - The project web page for matplotlib.
https://github.com/matplotlib/matplotlib - The source code for matplotlib.
http://matplotlib.org/gallery.html - A large gallery showcaseing various types of
plots matplotlib can create. Highly recommended!
http://www.loria.fr/~rougier/teaching/matplotlib - A good matplotlib tutorial.
http://scipy-lectures.github.io/matplotlib/matplotlib.html - Another good
matplotlib reference.