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

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.