7. Plotting using matplotlib

In this chapter we explore some of the graphical functionality of Python. We first import the required libraries for plotting.

import numpy as np
import matplotlib.pyplot as plt
# The seaborn package makes your plots look nicer
import seaborn as sns
# Imports system time module to time your script
import time

plt.close('all')  # close all open figures
tic = time.perf_counter()

7.1. Plotting Vectors and Arrays

7.1.1. Plotting Simple Vectors

We first define a grid vector xv. We then plot the first vector using the plot() command in the following figure:

xv = np.array([1, 2, 3, 4, 5])
carsv = np.array([1, 3, 6, 4, 9])

plt.plot(xv, carsv, 'b-', linewidth=2)
plt.title('Cars', fontsize=14)
# Save graphs in subfolder Graphs under name: fig1.pdf
plt.savefig('./Graphs/fig0.pdf')
plt.show()
_images/Slides_Plot_Fig0Autos_1.png
print("Time passed in seconds is = {:4.4f}".format(time.perf_counter() - tic))
Time passed in seconds is = 0.5719

7.1.2. Plotting Two Vectors

We first define a couple of vectors.

# Define vectors with 5 values each
xv     = np.array([1, 2, 3, 4, 5])
carsv   = np.array([1, 3, 6, 4, 9])
trucksv = np.array([2, 5, 4, 5, 12])
suvsv   = np.array([4, 4, 6, 6, 16])

We then plot the carsv and the trucksv vector into one graph. Compare the next figure.

fig, ax = plt.subplots()
ax.plot(xv,carsv, 'k-o', xv,trucksv,'b-.')
# Create a title with a red, bold/italic font
ax.set_title('Autos')
ax.legend(['cars', 'trucks'],loc='best')
plt.show()
_images/Slides_Plot_Fig2Autos_1.png

7.1.3. Graph 3 Car Types

Finally, we graph all three car types into one figure. This time we save the graph as fig1.pdf into subfolder Graphs.

fig, ax = plt.subplots()
ax.plot(xv, carsv, 'b-o', xv, trucksv,'r-^', xv, suvsv, 'g:s')
ax.set_title('Autos')
ax.set_xlabel('Days')
ax.set_ylabel('Total')
ax.set_xlim([0.5,5.5])
#ylim(min(cars,trucks),max(cars,trucks))
# Create a legend
ax.legend(['cars', 'trucks', 'suvs'], loc = 'best')
# Save graphs in subfolder Graphs under name: fig1.pdf
plt.savefig('./Graphs/fig1.pdf')
plt.show()
_images/Slides_Plot_Fig3Autos_1.png

7.2. Plotting Functions

7.2.1. First Example

If we want to plot a more general function like the \(y = \sqrt{x}\) we first need to define a grid of x values and then calculate the corresponding y-values for each grid point. This results in x and y coordinates for a number of points that we can then add to a coordinate system. After connecting these points in the graph, we get our function plot of the square root function.

Table 7.1 Plot Table for Square Root Function

x

y

0

\(\sqrt{0}\)

1

\(\sqrt{1}\)

2

\(\sqrt{2}\)

3

\(\sqrt{3}\)

4

\(\sqrt{4}\)

Each row represents the x and y coordinates of points that we now plot into the coordinate system. Let’s define the vectors first.

import numpy as np
import matplotlib.pyplot as plt

xv = np.array([0, 1, 2, 3, 4])
yv = np.zeros(len(xv))


print('--------------')
print('x      |    y  ')
print('--------------')
for i in range(len(xv)):
    yv[i] = np.sqrt(xv[i])
    print('{:5.2f}  | {:5.2f}'.format(xv[i],yv[i]))

print('--------------')
--------------
x      |    y
--------------
 0.00  |  0.00
 1.00  |  1.00
 2.00  |  1.41
 3.00  |  1.73
 4.00  |  2.00
--------------

We next plot these points into a coordinate system using the plot() function from the matplotlib.pyplot sub-library.

plt.plot(xv, yv, 'o')
plt.show()
_images/Slides_Plot_Fig0SquareRoot_1.png

If you would like to connect the dots, you can change the code to:

plt.plot(xv, yv, '-o')
plt.show()
_images/Slides_Plot_Fig1SquareRoot_1.png

This graph looks still a bit choppy. If you would like a smoother graph you need to evaluate the function using more points. We can also generate the x-grid automatically using the linspace function from the numpy library. We then calculate the corresponding y values with :math:` y = sqrt(x)` for each one of the x grid-points and record them in a yv vector.

xv = np.linspace(0, 4, 30) # Generates 30 points between 0 and 4
yv = np.zeros(len(xv))

for i in range(len(xv)):
    yv[i] = np.sqrt(xv[i])


plt.plot(xv, yv, '-o')
plt.show()
_images/Slides_Plot_Fig2SquareRoot_1.png

Finally we use a very powerful feature that all functions of the numpy library have in common. It is called vector evaluation. This means that any function in the numpy library can be applied on a vector without a loop which results in a new vector containing the results of the function evaluations on each point in the original vector. Sounds complicated but is really easy. And just to make the function even smoother we add some more points and plot it in the color red, look:

xv = np.linspace(0, 4, 50) # Generates 30 points between 0 and 4
yv = np.sqrt(xv)  # Vector evaluation, sqrt() is applied to each point in xv

plt.plot(xv, yv, 'r-o')
plt.show()
_images/Slides_Plot_Fig3SquareRoot_1.png

7.2.2. Second Example Using subplots()

Here is another example of a simple function, the \(y = sin(x)\) function. When we plot this function we use a more powerful plotting function called subplots(). This will allow us to plot multiple graphs into a single figure. I now also add labels to the graph and a legend. We also use the sin() function from the numpy library which allows us to use vector evaluation again so that we do not have to write a loop to evaluate the x-grid values.

Note

You should always have a title and labels in your figures!

xv = np.linspace(0, 10, 200)
yv = np.sin(xv)

fig, ax = plt.subplots()
ax.plot(xv, yv, 'r-', linewidth=2, label='sine function', alpha=0.6)
ax.set_title('Plotting the sin() function')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend(loc='best')
plt.show()
_images/Slides_Plot_Fig2Vectors_1.png

7.2.3. Plotting Multiple Functions into a Graph

Here is another example with some more functions. We again first define the input vector xv with the values we want to evaluate the function at and then specify the “output” vector yv as \(y = f(x)\). We use the following examples:

  • \(f(x) = 50 \times sin(x)\),

  • \(f(x) = x^2\),

  • \(f(x) = 3 \times (x^2)/2 - 5\), and finally

  • \(f(x) = 5 \times (x^2)/2 - \sqrt{x}\).

xv = np.arange(1, 10, 0.1)
y1v = 50*np.sin(xv)
y2v = xv**2
y3v = 3.0*(xv**2)/2 - 5
y4v = 5.0*(xv**2)/2 - np.sqrt(xv)

We have now two columns of values: x and y that we can plot against each other into a coordinate system.

fig, ax = plt.subplots()
ax.plot(xv, y1v, \
        xv, y2v, \
        xv, y3v, \
        xv, y4v)
ax.legend(['sin(x)', r'$x^2$', 'y3', 'y4'], loc = 'best')
ax.set_title('Many Functions')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
_images/Slides_Plot_Fig3Plots_1.png

7.3. Subplots

If we have more than one figure it might be good to put them all into one graph. In the following example we plot 6 figures into one picture. We plot into 3 rows and 2 columns. You can obviously rearrange all this.

# Creates  a 3 x 2 grid of subplots
num_rows = 3
num_cols = 2
title_size = 26

fig = plt.figure(figsize=(14, 16))
fig.suptitle("Figure with multiple subplots", \
    fontsize=title_size, fontweight='bold')
plt.subplots_adjust(wspace=0.2, hspace=0.3)

# [1]
ax = plt.subplot2grid((num_rows, num_cols), (0,0))
ax.plot([1,2,3])
ax.set_title('figure 1')
ax.set_xlabel('x')
ax.set_ylabel('y')
# [2]
ax = plt.subplot2grid((num_rows, num_cols), (0,1))
ax.plot(np.random.rand(12), np.random.rand(12), 'bo')
ax.set_title('figure 2')
ax.set_xlabel('x')
ax.set_ylabel('y')
# [3]
ax = plt.subplot2grid((num_rows, num_cols), (1,0))
ax.plot(np.array([1,2,3]), np.array([1,1,1]))
ax.set_title('figure 3')
ax.set_xlabel('x')
ax.set_ylabel('y')
# [4]
ax = plt.subplot2grid((num_rows, num_cols), (1,1))
ax.plot(np.linspace(1,12,12), np.random.rand(12), 'r^')
ax.set_title('figure 4')
ax.set_xlabel('x')
ax.set_ylabel('y')
# [5]
ax = plt.subplot2grid((num_rows, num_cols), (2,0))
ax.plot([1,2,1],':')
ax.set_title('figure 5')
ax.set_xlabel('x')
ax.set_ylabel('y')
# [6]
ax = plt.subplot2grid((num_rows, num_cols), (2,1))
ax.plot(np.linspace(1,12,12), np.random.rand(12), 'k-x')
ax.set_title('figure 6')
ax.set_xlabel('x')
ax.set_ylabel('y')

plt.show()
_images/Slides_Plot_Fig4Subplots_1.png

7.4. 3D-Graphs

Finally, we can also plot 3-D graphs in Python. The function we would like to plot is

\[f(x,y) = 3.0 \frac{y^2}{2.0} + x - \frac{\sqrt{x \times y}}{5.0}.\]

We start by defining an x-grid and a y-grid vector. We then evaluate the function at these values.

from mpl_toolkits.mplot3d import Axes3D

# Define x and y grid vectors
xv = np.arange(1, 10, 1)
yv = np.arange(1, 10, 1)
n = len(xv)

# Evaluation function at grid values
zv = 3 * yv**2 /2 + xv - np.sqrt(xv*yv) /5

# Use x,y,z as coordinates for points in 3D space
fig = plt.figure(figsize=(14, 16))
ax = Axes3D(fig)
ax.plot(xv, yv, zv, zdir='z', label='parametric curve')
ax.set_title('Function in 2 variables')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x,y)')
plt.show()
_images/Slides_Plot_Fig3DPlot_1.png

The problem with this approach is that the function gets only evaluated at the 45-degree line, that is at points (x=1, y=1), (x=2, y=2), …, (x=10, y=10). This is not really what we had in mind.

In order to plot the entire “surface” of the function \(f(x,y)\) we need to specify value pairs of x and y over the entire gridspace of the x/y plane. We use the command meshgrid in order to accomplish this. We then evaluate the function \(f(x,y)\) for each point on this “meshgrid” which results in a surface plot of the function.

from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(14, 16))
ax = plt.gca(projection='3d')

# Define grids in x and y dimension
xv = np.arange(1, 10, 1)
yv = np.arange(1, 10, 1)

# Span meshgrid over entire x/y plane
X, Y = np.meshgrid(xv, yv)

# Evaluate function at each point in the x/y plane
Z = 3.0 * Y**2.0 /2.0 + X - np.sqrt(X*Y) /5.0

# Plot the result
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap = plt.cm.jet, \
linewidth=0, antialiased=False)
ax.set_title('Function in 2 variables')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x,y)')
plt.show()
_images/Slides_Plot_Fig_Surface_1.png

7.5. 3D-Utility Function Graphs

We first start with some definitions of the consumption and leisure grid. We then evaluate the utility at all the consumption-leisure combination points.

titleSize = 26
legendSize = 16
labelSize = 18
tickSize = 16

# Define grids in x and y dimension
lv = np.linspace(0.0, 1.05, 20)
cv = np.linspace(0.0, 1.05, 20)

# Span meshgrid over entire x/y plane
L,C = np.meshgrid(lv, cv)

# Evaluate function at each point in the x/y plane
U = np.sqrt(L) + np.sqrt(C)

We can now plot the utility function. We plot it first as Wire-Frame graph.

# Plot the result
fig = plt.figure(figsize=(10, 10))
ax = Axes3D(fig)
ax.plot_wireframe(L,C, U, rstride=1, cstride=1)
ax.set_title(r'Utility Function: $U(c,l)=\sqrt{c}+\sqrt{l}$', fontsize=titleSize)
ax.set_xlabel('l', fontsize=labelSize)
ax.set_ylabel('c', fontsize=labelSize)
ax.set_zlabel('U(c,l)', fontsize=labelSize)
ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.view_init(elev=25., azim=225)
_images/Slides_Plot_Fig3DUtility_Wire_1.png

We can also fill in the graph a bit more using the plot_surface command.

# Plot the result
fig = plt.figure(figsize=(10, 10))
ax = Axes3D(fig)
ax.plot_surface(L,C, U, rstride=1, cstride=1, cmap = plt.cm.jet, \
                linewidth=0, antialiased=False)
ax.set_title(r'Utility Function: $U(c,l)=\sqrt{c}+\sqrt{l}$', fontsize=titleSize)
ax.set_xlabel('l', fontsize=labelSize)
ax.set_ylabel('c', fontsize=labelSize)
ax.set_zlabel('U(c,l)', fontsize=labelSize)
ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.view_init(elev=25., azim=225)
_images/Slides_Plot_Fig3DUtility_1.png

We next plot some of the indifference curves into the utility “mountain”.

fig = plt.figure(figsize=(10, 10))
ax = Axes3D(fig)
ax.contour(L,C, U, linewidths=3)
ax.view_init(elev=25., azim=225)
ax.set_title(r'Indifference Curves: $U(c,l)=\sqrt{c}+\sqrt{l}$', fontsize=titleSize)
ax.set_xlabel('l', fontsize=labelSize)
ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.set_ylabel('c', fontsize=labelSize)
ax.set_zlabel('U(c,l)', fontsize=labelSize)
Text(0.5, 0, 'U(c,l)')
_images/Slides_Plot_Fig3DUtility_Indiff_1.png

We next show the 2-dimensional representation of the indifference curves.

fig, ax = plt.subplots(figsize=(10, 10))
CS=ax.contour(L,C, U, linewidths=3)
ax.set_title(r'Indifference Curves: $U(c,l)=\sqrt{c}+\sqrt{l}$', fontsize=titleSize)
ax.set_xlabel('l', fontsize=labelSize)
ax.set_ylabel('c', fontsize=labelSize)
ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.clabel(CS, inline=1, fontsize=14)
<a list of 6 text.Text objects>
_images/Slides_Plot_Fig2DUtility_Indiff_1.png

7.6. Key Concepts and Summary

Note

  • A vector is a list of numbers.

  • The plot command needs two vectors that hold the coordinates of points you would like to plot

  • Use titles and label the axes in your plots.

7.7. Self-Check Questions

Todo

  1. Plot the following function: \(y = ln(x)\)

  2. Plot a straight horizontal line at y value of 5 in a range of x between -3 and 5.

  3. Plot a vertical line at x position 3 that goes from y = 0 to y = 9.