Matplotlib
Matplotlib is a Python package for 2D plotting and the matplotlib.pyplot
sub-module contains many plotting functions to create various kinds of plots. Let's get started by importing matplotlib.pyplot
.
import numpy as np
import matplotlib.pyplot as plt
Basic Plotting
Procedure
The general procedure to create a 2D line plot is:
- Create a sequence of $x$ values.
- Create a sequence of $y$ values.
- Enter
plt.plot(x,y,[fmt],**kwargs)
where[fmt]
is a (optional) format string and**kwargs
are (optional) keyword arguments specifying line properties of the plot. - Use
pyplot
functions to add features to the figure such as a title, legend, grid lines, etc. - Enter
plt.show()
to display the resulting figure.
Let's begin with a basic example with a few random points:
x = [-5,-2,0,1,3]
y = [2,-1,1,-4,3]
plt.plot(x,y)
plt.show()
The main things to notice are:
- The sequences
x
andy
define the coordinates of the points in the plot. - The line in the plot is constructed by connecting the points by straight lines.
The second observation implies that if we want to plot a smooth curve then we need to plot lots of points otherwise the plot will not be smooth. For example, we could try plotting the parabola $y = x^2$ for $x \in [-2,2]$ using only 5 points:
x = [-2,-1,0,1,2]
y = [4,1,0,1,4]
plt.plot(x,y)
plt.show()
This is too few points to plot a smooth curve such as $y = x^2$ and so we need more points! Let's try again using the NumPy function np.linspace
to create 100 points!
x = np.linspace(-2,2,100)
y = x**2
plt.plot(x,y)
plt.show()
That's a better representation of the parabola $y = x^2$. Note that the number of points we use in a line plot (100 in this case) is completely arbitrary but the goal is to show a smooth graph for a smooth curve and so we just need to pick a big enough number depending on the function. But be careful not to generate too many points since a very large number of points will take a long time to plot!
Now that we have the general idea, let's look at adding style and features to our plots!
Line Properties
A line appearing in a plot has several properties including color, transparency, style, width and markers. We can set these properties when we call plt.plot
using the following keyword arguments:
Property | Description |
---|---|
alpha |
transparency (0.0 transparent through 1.0 opaque) |
color (or c ) |
any matplotlib color |
label |
text appearing in legend |
linestyle (or ls ) |
solid , dashed , dashdot , dotted |
linewidth (or lw ) |
set width of the line |
marker |
set marker style |
markeredgecolor (or mec ) |
any matplotlib color |
markerfacecolor (or mfc ) |
any matplotlib color |
markersize (or ms ) |
size of the marker |
Note that we can specify a matplotlib color in several different ways including by name such as blue
or red
, or by a RGB tuple such as (1,0,1)
for purple. For example, let's plot the function
$$ y = e^{-x^2}\cos(2 \pi x) \ \ , \ \ x \in [-2,2] $$
x = np.linspace(-2,2,41)
y = np.exp(-x**2) * np.cos(2*np.pi*x)
plt.plot(x,y,alpha=0.4,label='Decaying Cosine',
color='red',linestyle='dashed',linewidth=2,
marker='o',markersize=5,markerfacecolor='blue',
markeredgecolor='blue')
plt.ylim([-2,2])
plt.legend()
plt.show()
Notice that we used the pyplot function plt.legend
to display the figure with a legend (showing the line label) and and plt.ylim
to set the limits on the vertical axis to [-2,2]
.
Format Strings
A format string gives us a shortcut to add color, markers and line style to a line plot. For example, if we want to plot the function
$$ y = \frac{1}{1 + x^2} \ , \ x \in [-5,5] $$
with a dashed black line and square markers, we could use keyword arguments:
x = np.linspace(-5,5,41)
y = 1/(1 + x**2)
plt.plot(x,y,color='black',linestyle='dashed',marker='s')
plt.show()
Or we could use the corresponding format string 'ks--'
where k
denotes a black line, s
a square marker and --
a dashed line:
x = np.linspace(-5,5,41)
y = 1/(1 + x**2)
plt.plot(x,y,'ks--')
plt.show()
Much easier! See below for a list of colors, markers and linestyles.
Colors
Character | Color |
---|---|
b |
blue |
g |
green |
r |
red |
c |
cyan |
m |
magenta |
y |
yellow |
k |
black |
w |
white |
Markers
Character | Marker |
---|---|
. |
point |
o |
circle |
v |
triangle down |
^ |
triangle up |
s |
square |
p |
pentagon |
* |
star |
+ |
plus |
x |
x |
D |
diamond |
Line Styles
Character | Line Style |
---|---|
- |
solid line style |
-- |
dashed line style |
-. |
dash-dot line style |
: |
dotted line style |
See the matplotlib.pyplot.plot documentation for more options.
Pyplot Functions
There are many pyplot
functions available for us to customize our figures. For example:
Fucntion | Description |
---|---|
plt.xlim |
set $x$ limits |
plt.ylim |
set $y$ limits |
plt.grid |
add grid lines |
plt.title |
add a title |
plt.xlabel |
add label to the horizontal axis |
plt.ylabel |
add label to the vertical axis |
plt.axis |
set axis properties (equal , off , scaled , etc.) |
plt.xticks |
set tick locations on the horizontal axis |
plt.yticks |
set tick locations on the vertical axis |
plt.legend |
display legend for several lines in the same figure |
plt.savefig |
save figure (as .png, .pdf, etc.) to working directory |
plt.figure |
create a new figure and set its properties |
See the pyplot documentation for a full list of functions.
Examples
Taylor Polynomials
Plot the function $y = \cos(x)$ along with its Taylor polynomials of degrees 2 and 4.
x = np.linspace(-6,6,50)
# Plot y = cos(x)
y = np.cos(x)
plt.plot(x,y,'b',label='cos(x)')
# Plot degree 2 Taylor polynomial
y2 = 1 - x**2/2
plt.plot(x,y2,'r-.',label='Degree 2')
# Plot degree 4 Taylor polynomial
y4 = 1 - x**2/2 + x**4/24
plt.plot(x,y4,'g:',label='Degree 4')
# Add features to our figure
plt.legend()
plt.grid(True,linestyle=':')
plt.xlim([-6,6])
plt.ylim([-4,4])
plt.title('Taylor Polynomials of cos(x) at x=0')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Heart Curve
Plot the heart curve:
\begin{align} x &= 16 \sin^3(t) \\ y &= 13 \cos(t) - 5 \cos(2t) - 2 \cos(3t) - \cos(4t) \end{align}
for $t \in [0,2\pi]$.
t = np.linspace(0,2*np.pi,100)
x = 16*np.sin(t)**3
y = 13*np.cos(t) - 5*np.cos(2*t) - 2*np.cos(3*t) - np.cos(4*t)
# Plot line with RGB tuple (red=1, green=0.2, blue=0.5)
# and 20pt line width
plt.plot(x,y,c=(1,0.2,0.5),lw=20)
# Add features to our figure
plt.title('Heart!')
plt.axis('equal')
plt.axis('off')
plt.show()
Subplots
The plt.subplot
function takes at least 3 inputs $n$, $m$ and $i$ and creates a figure with a $n$ by $m$ grid of subplots and then sets the $i$th subplot (counting across the rows) as the current plot (ie. current axes object).
For example, consider the sawtooth wave
$$ f(t) = \frac{1}{2} - \frac{1}{\pi} \sum_{k=1}^{\infty} (-1)^k \frac{\sin(2 \pi k t)}{k} $$
and let $f_N(t)$ denote the $N$th partial sum of the sawtooth wave:
$$ f_N(t) = \frac{1}{2} - \frac{1}{\pi} \sum_{k=1}^{N} (-1)^k \frac{\sin(2 \pi k t)}{k} $$
Create a 2 by 2 grid of subplots to plot the first 4 partial sums:
\begin{align} f_1(t) &= \frac{1}{2} + \frac{\sin(2 \pi t)}{\pi} \\ f_2(t) &= \frac{1}{2} + \frac{\sin(2 \pi t)}{\pi} - \frac{\sin(4 \pi t)}{2\pi} \\ f_3(t) &= \frac{1}{2} + \frac{\sin(2 \pi t)}{\pi} - \frac{\sin(4 \pi t)}{2\pi} + \frac{\sin(6 \pi t)}{3\pi} \\ f_4(t) &= \frac{1}{2} + \frac{\sin(2 \pi t)}{\pi} - \frac{\sin(4 \pi t)}{2\pi} + \frac{\sin(6 \pi t)}{3\pi} - \frac{\sin(8 \pi t)}{4\pi} \end{align}
t = np.linspace(0,4,200)
fN = 1/2
for N in [1,2,3,4]:
fN = fN - (-1)**N * np.sin(2*N*np.pi*t)/(N*np.pi)
plt.subplot(2,2,N)
plt.plot(t,fN)
plt.title('N = {}'.format(N))
plt.tight_layout()
plt.show()
See the documentation for more about subplots.
Beyond Line Plots
Scatter plots
A scatter plot has 4 dimensions: $x$ coordinate, $y$ coordinate, size and color. Let's make a random scatter plot:
# Set the number of dots in the plot
N = 2000
# Create random x and y coordinates sampled uniformly from [0,1]
x = np.random.rand(N)
y = np.random.rand(N)
# Create random array sampled uniformly from [20,120]
# `size` array is used below to set the size of each dot
size = 100*np.random.rand(N) + 20
# Create random 4-tuples sampled uniformly from [0,1]
# `colors` array is used below to set the color
# (red,green,blue,alpha) of each dot
colors = np.random.rand(N,4)
# Create a figure of size 12 by 5 and create scatter plot
plt.figure(figsize=(12,5))
plt.scatter(x,y,c=colors,s=size)
plt.axis('off')
plt.show()
Histograms
Generate an array of 10000 random numbers sampled from the normal distribution and create a histogram. Let's also superimpose the normal distribution:
$$ y = \frac{1}{\sqrt{2\pi}} e^{-x^2/2} $$
samples = np.random.randn(10000)
plt.hist(samples,bins=20,density=True,alpha=0.5,color=(0.3,0.8,0.1))
plt.title('Random Samples - Normal Distribution')
plt.ylabel('Frequency')
x = np.linspace(-4,4,100)
y = 1/(2*np.pi)**0.5 * np.exp(-x**2/2)
plt.plot(x,y,'b',alpha=0.8)
plt.show()
Bar plots
Plot the total precipitation in Vancouver by month as a bar plot:
month = range(1,13)
precipitation = [98.8,128.8,206.0,138.5,102.2,46.4,1.8,5.0,29.4,114.8,197.0,170.6]
plt.bar(month,precipitation)
plt.xticks(month)
plt.yticks(range(0,300,50))
plt.grid(True,alpha=0.5,linestyle='--')
plt.title('Precipitation in Vancouver, 2017')
plt.ylabel('Total Precipitation (mm)')
plt.xlabel('Month')
plt.show()
Figure and Axes Objects
Under construction
Exercises
Exercise 1. Plot the following functions:
- $f(x) = \sqrt{|x|}$, $x \in [-9,9]$
- $f(x) = \sin(x) + \sin(2x)$, $x \in [0,4\pi]$
- $f(x) = \arctan(x)$, $x \in [-5,5]$
- $f(x) = 2x\ln|x|$, $x \not=0$, $f(0)=0$, $x \in [-1,1]$
- $f(x) = (x+2)(x+1)(x-1)(x-2)(x - 3)$, $x \in [-2,3]$
- $f(x) = e^{-x^2}$, $x \in [-2,2]$
Exercise 2. Plot the figure eight curve:
\begin{align} x &= \sin(t) \\ y &= \sin(t) \cos(t) \end{align}
for $t \in [0,2\pi]$.
Exercise 3. Plot the trefoil knot:
\begin{align} x &= \sin t + 2 \sin 2t \\ y &= \cos t - 2 \cos 2t \end{align}
for $t \in [0,2\pi]$.
Exercise 4. Plot the butterfly curve:
\begin{align} x &= \sin(t) \left( e^{\cos t } - 2 \cos(4t) - \sin^5(t/12) \right) \\ y &= \cos(t) \left( e^{\cos t } - 2 \cos(4t) - \sin^5(t/12) \right) \end{align}
for $t \in [0,100]$.
Exercise 5. Write a function called parametric_plots
which takes input parameters a
and k
and plots the parametric equation
\begin{align} x(t) &= 2 k \cos(t) - a \cos(k t) \\ y(t) &= 2 k \sin(t) - a \sin(k t) \end{align}
for $t \in [0,2\pi]$. Include a title for each subplot to display the values for $a$ and $k$, and use plt.axis('equal')
to display the curve properly.