Matplotlib is a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms.
The first step is to set up our notebook environment so that matplotlib plots appear inline as images:
In [ ]:
%matplotlib inline
Next we import the matplotlib library's pyplot
interface; this interface is the simplest way to create new Matplotlib figures. To shorten this long name, we import it as plt
to keep things short but clear.
In [ ]:
import matplotlib.pyplot as plt
import numpy as np
Now we generate some data to use while experimenting with plotting:
In [ ]:
times = np.array([ 93., 96., 99., 102., 105., 108., 111., 114., 117.,
120., 123., 126., 129., 132., 135., 138., 141., 144.,
147., 150., 153., 156., 159., 162.])
temps = np.array([310.7, 308.0, 296.4, 289.5, 288.5, 287.1, 301.1, 308.3,
311.5, 305.1, 295.6, 292.4, 290.4, 289.1, 299.4, 307.9,
316.6, 293.9, 291.2, 289.8, 287.1, 285.8, 303.3, 310.])
Now we come to two quick lines to create a plot. Matplotlib has two core objects: the Figure
and the Axes
. The Axes
is an individual plot with an x-axis, a y-axis, labels, etc; it has all of the various plotting methods we use. A Figure
holds one or more Axes
on which we draw; think of the Figure
as the level at which things are saved to files (e.g. PNG, SVG)
Below the first line asks for a Figure
10 inches by 6 inches. We then ask for an Axes
or subplot on the Figure
. After that, we call plot
, with times
as the data along the x-axis (independant values) and temps
as the data along the y-axis (the dependant values).
In [ ]:
# Create a figure
fig = plt.figure(figsize=(10, 6))
# Ask, out of a 1x1 grid, the first axes.
ax = fig.add_subplot(1, 1, 1)
# Plot times as x-variable and temperatures as y-variable
ax.plot(times, temps)
From there, we can do things like ask the axis to add labels for x and y:
In [ ]:
# Add some labels to the plot
ax.set_xlabel('Time')
ax.set_ylabel('Temperature')
# Prompt the notebook to re-display the figure after we modify it
fig
We can also add a title to the plot:
In [ ]:
ax.set_title('GFS Temperature Forecast', fontdict={'size':16})
fig
Of course, we can do so much more...
In [ ]:
# Set up more temperature data
temps_1000 = np.array([316.0, 316.3, 308.9, 304.0, 302.0, 300.8, 306.2, 309.8,
313.5, 313.3, 308.3, 304.9, 301.0, 299.2, 302.6, 309.0,
311.8, 304.7, 304.6, 301.8, 300.6, 299.9, 306.3, 311.3])
Here we call plot
more than once to plot multiple series of temperature on the same plot; when plotting we pass label
to plot
to facilitate automatic creation. This is added with the legend
call. We also add gridlines to the plot using the grid()
call.
In [ ]:
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(1, 1, 1)
# Plot two series of data
# The label argument is used when generating a legend.
ax.plot(times, temps, label='Temperature (surface)')
ax.plot(times, temps_1000, label='Temperature (1000 mb)')
# Add labels and title
ax.set_xlabel('Time')
ax.set_ylabel('Temperature')
ax.set_title('Temperature Forecast')
# Add gridlines
ax.grid(True)
# Add a legend to the upper left corner of the plot
ax.legend(loc='upper left')
We're not restricted to the default look of the plots, but rather we can override style attributes, such as linestyle
and color
. color
can accept a wide array of options for color, such as red
or blue
or HTML color codes. Here we use some different shades of red taken from the Tableau color set in matplotlib, by using tab:red
for color.
In [ ]:
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(1, 1, 1)
# Specify how our lines should look
ax.plot(times, temps, color='tab:red', label='Temperature (surface)')
ax.plot(times, temps_1000, color='tab:red', linestyle='--',
label='Temperature (isobaric level)')
# Same as above
ax.set_xlabel('Time')
ax.set_ylabel('Temperature')
ax.set_title('Temperature Forecast')
ax.grid(True)
ax.legend(loc='upper left')
add_subplot
to create two different subplots on the figureax.set_xlim
and ax.set_ylim
to control the plot boundariessharex
and sharey
to add_subplot
to share plot limits
In [ ]:
# Fake dewpoint data to plot
dewpoint = 0.9 * temps
dewpoint_1000 = 0.9 * temps_1000
# Create the figure
fig = plt.figure(figsize=(10, 6))
# YOUR CODE GOES HERE
In [ ]:
# %load solutions/subplots.py
In [ ]:
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(1, 1, 1)
# Specify no line with circle markers
ax.plot(temps, temps_1000, linestyle='None', marker='o', markersize=5)
ax.set_xlabel('Temperature (surface)')
ax.set_ylabel('Temperature (1000 hPa)')
ax.set_title('Temperature Cross Plot')
ax.grid(True)
You can also use the scatter
methods, which is slower, but will give you more control, such as being able to color the points individually based upon a third variable.
In [ ]:
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(1, 1, 1)
# Specify no line with circle markers
ax.scatter(temps, temps_1000)
ax.set_xlabel('Temperature (surface)')
ax.set_ylabel('Temperature (1000 hPa)')
ax.set_title('Temperature Cross Plot')
ax.grid(True)
c
keyword argument to the scatter
call and color the points by the difference between the surface and 1000 hPa temperature.
In [ ]:
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(1, 1, 1)
# YOUR CODE GOES HERE
ax.set_xlabel('Temperature (surface)')
ax.set_ylabel('Temperature (1000 hPa)')
ax.set_title('Temperature Cross Plot')
ax.grid(True)
In [ ]:
# %load solutions/color_scatter.py
In [ ]:
x = y = np.arange(-3.0, 3.0, 0.025)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
Let's start with a simple imshow plot.
In [ ]:
fig, ax = plt.subplots()
im = ax.imshow(Z, interpolation='bilinear', cmap='RdYlGn',
origin='lower', extent=[-3, 3, -3, 3])
We can also create contours around the data.
In [ ]:
fig, ax = plt.subplots()
ax.contour(X, Y, Z)
In [ ]:
fig, ax = plt.subplots()
c = ax.contour(X, Y, Z, levels=np.arange(-2, 2, 0.25))
ax.clabel(c)
In [ ]:
fig, ax = plt.subplots()
c = ax.contourf(X, Y, Z)
In [ ]:
# YOUR CODE GOES HERE
In [ ]:
# %load solutions/imshow_contour.py