Generate Contour Plots Using Python’s Matplotlib

Original article was published by Rashida Nasrin Sucky on Artificial Intelligence on Medium


Generate Contour Plots Using Python’s Matplotlib

A simple and easy tutorial on making Contour plots

I am sure you have seen a contour plot before. At least in weather data. It is used a lot in presenting meteorological or geographical data. But it is also used to present density, brightness, and electric potential. It is used a lot in data analysis and machine learning. It shows how a response variable relates to two predictor variables.

It gives a two-dimensional view where all the points having the same response are connected by a line. That line is a contour line.

Three main elements of a contour plot:

  1. x-axis and the y-axis shows the predictors
  2. Contour lines to represent the same response values
  3. Colored bands that provide a range of response values

Here is how to draw a contour plot

First import the necessary packages.

import numpy as np
import matplotlib.pyplot as plt
import pylab

Let’s generate some x and y values

xp = np.arange(-8, 10, 2)
yp = np.arange(-8, 10, 2)

You can probably imagine how ‘xp’ and ‘yp’ look like. But still, just have a look.

xp

Output:

array([-8, -6, -4, -2,  0,  2,  4,  6,  8])

Input:

yp

Output:

array([-8, -6, -4, -2,  0,  2,  4,  6,  8])

The length of x and y is 9.

This information is important because we need to generate z using this number.

First, initiate a random z point of the shape 9 x 9

zp = np.ndarray((9,9))
zp

Output:

array([[1.20117830e-311, 1.20117830e-311, 1.20120150e-311,
1.20120150e-311, 1.20120150e-311, 1.20120150e-311,
1.20118338e-311, 1.20119781e-311, 1.20120151e-311],
[1.20120150e-311, 1.20120151e-311, 1.20117830e-311,
1.20117830e-311, 1.20118045e-311, 1.20120150e-311,
1.20119863e-311, 1.20119863e-311, 1.20117830e-311],
[1.20119864e-311, 1.20118316e-311, 1.20117850e-311,
1.20117830e-311, 1.20118500e-311, 1.20118500e-311,
1.20118490e-311, 1.20118488e-311, 1.20118316e-311],
[1.20118500e-311, 1.20118493e-311, 1.20118493e-311,
1.20118493e-311, 1.20118493e-311, 1.20118339e-311,
1.20117862e-311, 1.20117835e-311, 1.20118337e-311],
[1.20118339e-311, 1.20118338e-311, 1.20118347e-311,
1.20118348e-311, 1.20118339e-311, 1.20118348e-311,
1.20118316e-311, 1.20118338e-311, 1.20118348e-311],
[1.20118339e-311, 1.20118348e-311, 1.20118347e-311,
1.20118348e-311, 1.20118348e-311, 1.20118348e-311,
1.20118339e-311, 1.20118339e-311, 1.20118333e-311],
[1.20118348e-311, 1.20118348e-311, 1.20118348e-311,
1.20117830e-311, 1.20117830e-311, 1.20117853e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311],
[1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311],
[1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 0.00000000e+000]])

Now, I will replace these random values with a formula of my choice. you can use the formula you want or you need.

for x in range(0, len(xp)):
for y in range(0, len(yp)):
zp[x][y] = xp[x]**2 + yp[y]**2
zp

Output:

array([[128., 100.,  80.,  68.,  64.,  68.,  80., 100., 128.],
[100., 72., 52., 40., 36., 40., 52., 72., 100.],
[ 80., 52., 32., 20., 16., 20., 32., 52., 80.],
[ 68., 40., 20., 8., 4., 8., 20., 40., 68.],
[ 64., 36., 16., 4., 0., 4., 16., 36., 64.],
[ 68., 40., 20., 8., 4., 8., 20., 40., 68.],
[ 80., 52., 32., 20., 16., 20., 32., 52., 80.],
[100., 72., 52., 40., 36., 40., 52., 72., 100.],
[128., 100., 80., 68., 64., 68., 80., 100., 128.]])

So, we have x, y, and z data ready. Here is how to do the contour plot.

plt.figure(figsize=(7, 5))
plt.title('Contour Plot')
contours = plt.contour(xp, yp, zp)
plt.clabel(contours, inline=1, fontsize=12)
plt.show()

Contour plot for saddle surface

I will do the exact same procedure with a slightly different formula for z values. So I will not explain step by step this time:

xp = np.arange(-3, 4)
yp = np.arange(-3, 4)
zp =np.ndarray((7,7))for x in range(0, len(xp)):
for y in range(0, len(yp)):
zp[x][y] = xp[x]*xp[x] - yp[y]*yp[y]
plt.figure(figsize=(8, 6))
plt.title('Contour plot for saddle surface - Hyperbolic paraboloid')
contours = plt.contour(xp, yp, zp)
plt.clabel(contours, inline=1, fontsize=12)
plt.show()

Density Plot

This is a density plot. So I will make a different dataset where data points are closer. Here are x and y.

x = np.linspace(0, 5, 60)
y = np.linspace(0, 5, 48)

Both x and y are the same. This is how the data look like:

array([0.        , 0.08474576, 0.16949153, 0.25423729, 0.33898305,
0.42372881, 0.50847458, 0.59322034, 0.6779661 , 0.76271186,
0.84745763, 0.93220339, 1.01694915, 1.10169492, 1.18644068,
1.27118644, 1.3559322 , 1.44067797, 1.52542373, 1.61016949,
1.69491525, 1.77966102, 1.86440678, 1.94915254, 2.03389831,
2.11864407, 2.20338983, 2.28813559, 2.37288136, 2.45762712,
2.54237288, 2.62711864, 2.71186441, 2.79661017, 2.88135593,
2.96610169, 3.05084746, 3.13559322, 3.22033898, 3.30508475,
3.38983051, 3.47457627, 3.55932203, 3.6440678 , 3.72881356,
3.81355932, 3.89830508, 3.98305085, 4.06779661, 4.15254237,
4.23728814, 4.3220339 , 4.40677966, 4.49152542, 4.57627119,
4.66101695, 4.74576271, 4.83050847, 4.91525424, 5. ])

As before I need a function for z. Here is the function I choose,

def fn(x, y):
return np.sin(x)**5 + np.cos(y+17)**8

Now, time to prepare the X, Y, and Z data. I will simply use the np.meshgrid function on x and y which builds two-dimensional grids from one-dimensional arrays.

X, Y = np.meshgrid(x, y)
Z = fn(X, Y)

The data is ready. Here is the simplest, black and white density contour plot.

plt.contour(X, Y, Z, colors = 'black')

Let’s add a colormap also specify that we want 15 equally spaced lines drawn within the range.

plt.figure(figsize=(8, 6))
contours = plt.contour(X, Y, Z, 15, cmap = 'RdGy')
plt.clabel(contours, inline=True, fontsize=12)

There is another function in matplotlib that is contourf. Now, see an example of contourf.

plt.figure(figsize=(14, 10))
plt.contourf(X, Y, Z, 20, cmap = 'RdGy')
plt.colorbar()

One example of ‘imshow’:

plt.figure(figsize=(14, 10))
plt.imshow(Z, extent=[0,6,0,6], origin='upper', cmap='RdGy')
plt.colorbar()

We can even place that black and white contour plot on top of this imshow.

plt.figure(figsize=(14, 10))
contours = plt.contour(X, Y, Z, 15, colors='black')
plt.clabel(contours, inline=True, fontsize=12)
plt.imshow(Z, extent=[0,6,0,6], origin='upper', cmap='RdGy', alpha=0.5)
plt.colorbar()

I like it! How about you?

Conclusion

If you never made a contour plot before, I hope you will now whenever necessary. It gives a lot of information and also looks nice! If you are a machine learning modeler, use a contour plot to visualize the range in different classes or anomaly in the data.

Feel free to follow me on Twitter and like my Facebook page.

More Reading: