# Contour plots

Contour plots allow us to project a third dimension of data down onto an X, Y axis, be it a functional relationship between two dimensions of data or some decision threshold of a given model.

But before we can start plotting this third dimension of data, we have to figure out how to calculate it.

## Meshgrid

Say we’ve got two simple vectors, x and y.

%pylab inline

x = np.linspace(0, 10, 5)
y = np.linspace(0, 1, 4)
Populating the interactive namespace from numpy and matplotlib


x has length 5 and y has length 4

print(x)
print(x.shape)
print(y)
print(y.shape)
[  0.    2.5   5.    7.5  10. ]
(5,)
[ 0.          0.33333333  0.66666667  1.        ]
(4,)


We want to calculate a value for a third vector z ** at every point these two meet**, therefore, we need to express z with dimensions (len(x), len(y)).

This is where meshgrid() comes in.

xx, yy = np.meshgrid(x, y)

It produces a matrix xx where our original vector x is broadcast as each row, with the same number of rows as y has length.

print(xx)
print(xx.shape)
[[  0.    2.5   5.    7.5  10. ]
[  0.    2.5   5.    7.5  10. ]
[  0.    2.5   5.    7.5  10. ]
[  0.    2.5   5.    7.5  10. ]]
(4, 5)


Similarly, yy has each column as y vectors, with as many columns as there are x values.

print(yy)
print(yy.shape)
[[ 0.          0.          0.          0.          0.        ]
[ 0.33333333  0.33333333  0.33333333  0.33333333  0.33333333]
[ 0.66666667  0.66666667  0.66666667  0.66666667  0.66666667]
[ 1.          1.          1.          1.          1.        ]]
(4, 5)


Now because we have two matricies of the same dimensions, we can do element-wise calculations and preserve our dimensions.

z = xx + yy
z.shape
(4, 5)

z = xx ** yy
z.shape
(4, 5)

z = xx > yy
z.shape
(4, 5)


## Contour

Now that we know how to get clean values for Z, generating a contour plot is a simple call to plt.contour()

X = np.linspace(0, 1, 1000)
Y = np.linspace(0, 1, 1000)

xx, yy = np.meshgrid(X, Y)

Z = xx ** 2 - yy 

Ez pz

plt.contour(X, Y, Z)
<matplotlib.contour.QuadContourSet at 0x1f8bf254eb8>


### Labelling Lines

Labelling the contours is also pretty simple. You may have noticed that the call to contour() returned a matplotlib.contour.QuadContourSet object. If we catch this, we can pass it as an argument to ax.clabel()

fig, ax = plt.subplots()
cs = ax.contour(X, Y, Z)
ax.clabel(cs)

# adjusting axis because my X, Y were
# pooly-chosen, lol
ax.set_xlim(0, 1.2)
ax.set_ylim(0, 1.2)
(0, 1.2)


### Filled Contour

Filling in the contours is just as simple– merely tacking an f onto the function name!

plt.contourf(X, Y, Z)
<matplotlib.contour.QuadContourSet at 0x1f8bf5f36d8>