Library: MatPlotLib

Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations in Python. All graphic-related codes should be in one cell.

Installation

In [1]:
#!pip install matplotlib

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
In [2]:
#shows graphic without 'plt.show()'
%matplotlib inline 
In [3]:
# creating two variables to represent
x = np.linspace(0, 5, 11)
y = x ** 2
display(x)
display(y)
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])
array([ 0.  ,  0.25,  1.  ,  2.25,  4.  ,  6.25,  9.  , 12.25, 16.  ,
       20.25, 25.  ])

Creating figure

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).
In [4]:
#Create figure
fig = plt.figure()
<Figure size 432x288 with 0 Axes>
In [5]:
#Figure size and DPI
fig = plt.figure(figsize=(8,4), dpi=100)
<Figure size 800x400 with 0 Axes>
In [6]:
#Subplots layout
fig, axes = plt.subplots(nrows=1, ncols=2)
In [7]:
#Figure size in subplots
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12,3))
In [8]:
# Multiple plots in the same 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

Adding and ploting axes

In [9]:
# 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')
Out[9]:
[<matplotlib.lines.Line2D at 0x1af557c0a88>]

Setting colors, linewidths, linetypes

Colors with the color= parameter

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.

In [10]:
fig, ax = plt.subplots()

ax.plot(x, x+2, color="blue") # by colour name
ax.plot(x, x+3, color="#FF8C00") # RGB hex code 
ax.plot(x, x+1, color="blue", alpha=0.5) # half-transparant
Out[10]:
[<matplotlib.lines.Line2D at 0x1af5492bb08>]

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:

In [11]:
#Line width
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)
Out[11]:
[<matplotlib.lines.Line2D at 0x1af55a6ae08>]
In [12]:
#Line type
fig, ax = plt.subplots(figsize=(12,6))

# 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])
In [13]:
#Marker symbols
fig, ax = plt.subplots(figsize=(12,6))

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')
Out[13]:
[<matplotlib.lines.Line2D at 0x1af55b1df88>]
In [14]:
# marker size and color
fig, ax = plt.subplots(figsize=(12,6))

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");

Ploting title and axes labels

A title can be added to each axis instance in a figure. To set the title, use the set_title method.

In [15]:
ax.set_title("title");

Similarly, with the methods set_xlabel and set_ylabel, we can set the labels of the X and Y axes:

In [16]:
ax.set_xlabel("x")
ax.set_ylabel("y");
In [17]:
# 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')

#Plot axis labels and title
axes.set_title('Set Title')
axes.set_xlabel('Set X Label') # Notice the use of set_ to begin methods
axes.set_ylabel('Set y Label')
Out[17]:
Text(0, 0.5, 'Set y Label')

Plotting legend

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:

In [18]:
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()
Out[18]:
<matplotlib.legend.Legend at 0x1af55cb2d48>
In [19]:
# Legend position
ax.legend(loc=0) # 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
Out[19]:
<matplotlib.legend.Legend at 0x1af55cdfb08>

Axes configuration

Axes 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:

In [20]:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

axes.plot(x, x**2, x, x**3)
axes.set_ylim([0, 60])
axes.set_xlim([2, 5])
axes.set_title("custom axes range");
In [21]:
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")
Out[21]:
Text(0.5, 1.0, 'tight axes')

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):

In [22]:
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)");

Ticks and custom 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:

In [23]:
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

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

Scientific notation

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

In [24]:
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

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 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:

In [25]:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

# default grid appearance
axes.plot(x, x**2, x, x**3, lw=2)
axes.grid(True)
In [26]:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

# custom grid appearance
axes.plot(x, x**2, x, x**3, lw=2)
axes.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)

Axis spines

In [27]:
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])

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:

In [28]:
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

In [29]:
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);

Text annotation

In [30]:
fig, ax = plt.subplots()

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

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

Multiplots

In [31]:
# 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');
In [32]:
fig, axes = plt.subplots(nrows=1, ncols=2)

for ax in axes:
    ax.plot(x, y, 'g')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('title')

fig    
plt.tight_layout() #automatically adjusts so that there is no overlapping content

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:

In [33]:
fig.savefig("filename.png")
fig.savefig("filename.png", dpi=200) #specify DPI

Other Plot Types

There are many specialized plots we can create, such as barplots, histograms, scatter plots, and much more.

In [34]:
n = np.array([0,1,2,3,4,5])

Scatter plot

In [35]:
plt.scatter(x,y)
Out[35]:
<matplotlib.collections.PathCollection at 0x1af571dfe08>
In [36]:
fig1 = plt.figure()
axes = fig1.add_axes([0.1, 0.1, 0.8, 0.8])

axes.scatter(xx, xx + 0.25*np.random.randn(len(xx)))
Out[36]:
<matplotlib.collections.PathCollection at 0x1af571dfbc8>

Histogram

In [37]:
from random import sample
data = sample(range(1, 1000), 100)
plt.hist(data)
Out[37]:
(array([10.,  7., 16., 14.,  8.,  5.,  8.,  9.,  9., 14.]),
 array([ 25. , 118.9, 212.8, 306.7, 400.6, 494.5, 588.4, 682.3, 776.2,
        870.1, 964. ]),
 <a list of 10 Patch objects>)

Bar plot

In [38]:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])

axes.bar(n, n**2, align="center", width=0.5, alpha=0.5)
Out[38]:
<BarContainer object of 6 artists>
In [39]:
## Box plot
In [40]:
data = [np.random.normal(0, std, 100) for std in range(1, 4)]

# rectangular box plot
plt.boxplot(data,vert=True,patch_artist=True);

Steps

In [41]:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])

axes.step(n, n**2, lw=2)
Out[41]:
[<matplotlib.lines.Line2D at 0x1af5702d108>]

Fill between

In [42]:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])

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

Color map

In [43]:
alpha = 0.7
phi_ext = 2 * np.pi * 0.5

def flux_qubit_potential(phi_m, phi_p):
    return 2 + alpha - 2 * np.cos(phi_p) * np.cos(phi_m) - alpha * np.cos(phi_ext - 2*phi_p)
In [44]:
phi_m = np.linspace(0, 2*np.pi, 100)
phi_p = np.linspace(0, 2*np.pi, 100)
X,Y = np.meshgrid(phi_p, phi_m)
Z = flux_qubit_potential(X, Y).T
In [45]:
# pcolor
fig, ax = plt.subplots()

p = ax.pcolor(X/(2*np.pi), Y/(2*np.pi), Z, cmap=plt.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max())
cb = fig.colorbar(p, ax=ax)
In [46]:
#imshow
fig, ax = plt.subplots()

im = ax.imshow(Z, cmap=plt.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 1, 0, 1])
im.set_interpolation('bilinear')

cb = fig.colorbar(im, ax=ax)
In [47]:
#contour
fig, ax = plt.subplots()

cnt = ax.contour(Z, cmap=plt.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 1, 0, 1])

Surface plot

In [48]:
from mpl_toolkits.mplot3d.axes3d import Axes3D

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=plt.cm.coolwarm, linewidth=0, antialiased=False)
cb = fig.colorbar(p, shrink=0.5)

Wire frame plot

In [49]:
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)

Coutor plot with projections

In [50]:
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=plt.cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='x', offset=-np.pi, cmap=plt.cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='y', offset=3*np.pi, cmap=plt.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);

Aesthetic

Style

In [51]:
x = np.linspace(0, 5, 11)
y = x ** 2

plt.plot(x, y)
Out[51]:
[<matplotlib.lines.Line2D at 0x1af587e9f88>]
In [52]:
plt.style.use('default')
plt.plot(x, y)
Out[52]:
[<matplotlib.lines.Line2D at 0x1af59431e48>]
In [53]:
plt.style.use('classic')
plt.plot(x, y)
Out[53]:
[<matplotlib.lines.Line2D at 0x1af595579c8>]
In [54]:
plt.style.use('bmh')
plt.plot(x, y)
Out[54]:
[<matplotlib.lines.Line2D at 0x1af59460048>]
In [55]:
plt.style.use('fivethirtyeight')
plt.plot(x, y)
Out[55]:
[<matplotlib.lines.Line2D at 0x1af5725bc08>]
In [56]:
plt.style.use('ggplot')
plt.plot(x, y)
Out[56]:
[<matplotlib.lines.Line2D at 0x1af58f34508>]
In [57]:
plt.style.use('grayscale')
plt.plot(x, y)
Out[57]:
[<matplotlib.lines.Line2D at 0x1af57226448>]
In [58]:
plt.style.use('dark_background')
plt.plot(x, y)
Out[58]:
[<matplotlib.lines.Line2D at 0x1af595a8208>]
In [59]:
plt.style.use('seaborn')
plt.plot(x, y)
Out[59]:
[<matplotlib.lines.Line2D at 0x1af594cfe48>]

Color

color by name qualitative colors diverging colormaps secuential colormaps1 secuential colormaps2 cycling colormaps miscelaneus uniform