Matplotlib is the most popular and mature library for plotting data using Python. It has all of the functionality you would expect, including the ability to control the formatting of plots and figures at a very fine level.
The official matplotlib documentation is at http://matplotlib.org/
The matplotlib gallery is at http://matplotlib.org/gallery.html
In [ ]:
# In IPython or the IPython notebook, it's easiest to use the pylab magic, which
# imports matplotlib, numpy, and scipy.
# The matplotlib notebook flag means that plots will be shown interactively in the
# notebooks, rather than in pop-up windows.
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
There are two major challenges with creating figures. First is understanding the syntax to actually make the basic plot appear. Second is formatting the basic plot to look exactly how you would like it to look. In general, the formatting will probably take you longer...
Within pyplot (currently imported as 'plt'), there are two basic ways to go about making plots - using the Matlab-like clone, and using the object-oriented approach. The latter provides better control over plot features, while only requiring slightly more typing. It's easy to quickly outgrow the Matlab clone, so we'll go right to the object-oriented syntax.
In simple matplotlib plotting, there are two concepts to distinguish:
Figure - the entire figure, like what you might see in a journal, including all subplots, axes, lines, labels, etc. The whole enchilada.
Subplot/Axes - one of the sub-sections of the figure, labeled (a), (b), etc. in articles. Each subplot will contain one Axes object, which is the container where all of the useful stuff, such as actual lines, legends, labels, etc., are actually housed.
For example, here's how to make one figure with two subplots, the second of which contains two lines.
In [ ]:
# First we make some data to plot
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
First, create an empty figure with 2 subplots using the subplots method
figure, axes = plt.subplots(rows, columns)
In [ ]:
fig, axes = plt.subplots(1,2)
Now let's actually plot the data using the plot method on an axis
axis.plot(x, y)
You can plot multiple lines on an axis
In [ ]:
fig, axes = plt.subplots(1,2)
# We plot one line on the first axis
axes[0].plot(x, y1)
# and both lines on the second axis
axes[1].plot(x, y1)
axes[1].plot(x, y2);
Many of the basic formatting problems you have will be solved by the magic of tight_layou
t. Before you start tweaking how you figure looks, try it out.
plt.tight_layout()
In [ ]:
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1)
axes[1].plot(x, y1)
axes[1].plot(x, y2)
plt.tight_layout();
To save your figure you can use the savefig
command:
fig.savefig('fileanme', format='png')
Format options include png, pdf, ps, eps and svg
In [ ]:
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1)
axes[1].plot(x, y1)
axes[1].plot(x, y2)
fig.savefig('first_plot.png', format='png');
In [ ]:
The formatting of figures often takes longer than actually setting them up and adding data. There are many different approaches to formatting figures in matplotlib (many goals can be accomplished in different ways, using different commands), and you will come across many of these as you learn more. The tips below give a few simple ways to get started.
The plot method has several available keyword arguments that you can use to change the line formatting.
In [ ]:
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1, color='r', linewidth=5)
axes[1].plot(x, y1, color='#ffaa00', linewidth=0.5, linestyle='--')
axes[1].plot(x, y2, color='green', linestyle='-.');
In [ ]:
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1, color='r', linewidth=5)
axes[1].plot(x, y1, color='#ffaa00', linewidth=0.5, linestyle='--')
axes[1].plot(x, y2, color='green', linestyle='-.')
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, 1]);
Oh no! That changed it for the last plot but not for the first plot.
To set each plot individually, you need to set the current axis to the subplot you are interested in using the method sca
. Then you can use xticks
and yticks
.
plt.sca(axis)
plt.xticks([val1, val2, val3])
plt.yticks([yval1, yval2, yval3])
In [ ]:
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1, color='r', linewidth=5)
axes[1].plot(x, y1, color='#ffaa00', linewidth=0.5, linestyle='--')
axes[1].plot(x, y2, color='green', linestyle='-.')
# Set the current axis to the first subplot
fig.sca(axes[0])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, 1])
# Set the current axis to the second subplot
fig.sca(axes[1])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, 1]);
Setting the limits of the axes is very similar to setting the ticks. The command to set the limits are xlim
and ylim
. Remember if you have more than one subplot, you will need to set the current axis before you set that axis' limits.
plt.sca(axis)
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
In [ ]:
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1, color='r', linewidth=5)
axes[1].plot(x, y1, color='#ffaa00', linewidth=0.5, linestyle='--')
axes[1].plot(x, y2, color='green', linestyle='-.')
# Set the current axis to the first subplot
fig.sca(axes[0])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, 1])
# set x and y limits
plt.xlim(-np.pi, np.pi)
plt.ylim(-1, 1)
# Set the current axis to the second subplot
fig.sca(axes[1])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, 1])
# set x and y limits
plt.xlim(-np.pi, np.pi)
plt.ylim(-1, 1);
In [ ]:
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig, axes = plt.subplots(1,2)
axes[0].plot(x, y1, color='r', linewidth=5)
axes[1].plot(x, y1, color='#ffaa00', linewidth=0.5, linestyle='--')
axes[1].plot(x, y2, color='green', linestyle='-.')
# Set the current axis to the first subplot
fig.sca(axes[0])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], ['-pi', '-pi/2', '0', 'pi/2', 'pi'])
# You probably don't want to set the labels when you just want the exact numbers.
plt.yticks([-1, 0, 1], ['-1', '0', '1'])
# set x and y limits
plt.xlim(-np.pi, np.pi)
plt.ylim(-1, 1)
# Set the current axis to the second subplot
fig.sca(axes[1])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], ['-pi', '-pi/2', '0', 'pi/2', 'pi'])
plt.yticks([-1, 0, 1], ['-1', '0', '1'])
# set x and y limits
plt.xlim(-np.pi, np.pi)
plt.ylim(-1, 1);
When you create a line on a plot, you can pass it a keyword argument label
and then create a legend that will use that label using the legend
method. The legend
method takes an optional parameter of loc
for the location of the legend. You can see the values allowed here: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend This is another one of those commands that you need to set the current axis if you have more than one subplot.
plt.plot(x,y, label='my_label')
plt.legend(loc='best')
In [ ]:
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig, axes = plt.subplots(1,2)
# Let's set labels here
axes[0].plot(x, y1, color='r', linewidth=5, label='sin(x)')
axes[1].plot(x, y1, color='#ffaa00', linewidth=0.5, linestyle='--', label='sin(x)')
axes[1].plot(x, y2, color='green', linestyle='-.', label='cos(x)')
# Set the current axis to the first subplot
fig.sca(axes[0])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], ['-pi', '-pi/2', '0', 'pi/2', 'pi'])
# You probably don't want to set the labels when you just want the exact numbers.
plt.yticks([-1, 0, 1], ['-1', '0', '1'])
plt.legend(loc='best')
# set x and y limits
plt.xlim(-np.pi, np.pi)
plt.ylim(-1, 1)
# Set the current axis to the second subplot
fig.sca(axes[1])
# set x and y ticks
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], ['-pi', '-pi/2', '0', 'pi/2', 'pi'])
plt.yticks([-1, 0, 1], ['-1', '0', '1'])
plt.legend(loc='upper right')
# set x and y limits
plt.xlim(-np.pi, np.pi)
plt.ylim(-1, 1);
In [ ]:
In the examples above, we used the plot method to make line plots. There are also methods to make scatter plots, barplots, histograms, loglog plots, semilog plots, etc.
# Bar graph
ax.bar(x, y)
# Scatter plot
ax.scatter(x,y)
# Horizontal bar plot
ax.barh(x,y)
# Boxplot
ax.boxplot(x)
# Log-log plot
ax.loglog(x,y)
# Semilog plot
ax.semilogx(x,y)
ax.semilogy(x,y)
Plots too squished? Check out plt.tight_layout()
In [ ]:
# Make some data to plot
x = np.arange(0, 100)
y = np.random.rand(100) # 100 random numbers
# Make a figure with 6 subplots and axes
# Notice that we are doing some arguement unpacking to get six subplots. You can use indexing instead if you prefer
fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(3, 2)
# Add data to each axis. Optional arguments to each method will customize each plot.
ax1.bar(x,y)
ax2.scatter(x,y)
ax3.barh(x,y)
ax4.boxplot(x)
ax5.loglog(x,y)
ax6.semilogx(x,y)
Many of the same formatting options as the line plot are available for these additional plots. There are also some other options. The gallery (section 5) is the best place to find all the options.
Let's try changing the marker on the scatter plot: http://matplotlib.org/exmples/lines_bars_and_markers/marker_reference.html
In [ ]:
fig, ax = plt.subplots(1,1)
ax.scatter(x, y, marker='x')
ax.scatter(x, y + 2, marker='>', color='#00aaff')
Matplotlib also makes it easy to plot images. For this, you can use the plot method imshow
(syntax borrowed from Matlab).
To load in an image we use the imread
function. This takes a file path and reads the file into a numpy ndarray
To plot an image, you can use imshow
function giving it an array.
A 1D array will be rendered as grayscale and a 3D or (4D with transparency) array will be a full color image.
To set the colormap of a grayscale image, you can use the optional cmap
key word argument to imshow
. Options available are listed here: http://matplotlib.org/examples/color/colormaps_reference.html
In [ ]:
# Read image from file and display it
img1 = plt.imread('astronaut.png')
# Uncomment following line to prove it still works without the alpha channel
# img1 = img1[:,:, 0:3]
fig, ax = plt.subplots(1,1)
ax.imshow(img1)
In [ ]:
# We can plot random noise in the viridis colormap.
img2 = np.random.rand(128, 128)
fig, ax = plt.subplots(1,1)
ax = ax.imshow(img2, cmap='viridis')
In [ ]:
It can be very intimidating to try to craft exactly the figure that you want, especially if you are used to being able to adjust things visually using a program like Excel.
If you get stuck and don't know where to start, or just want to learn more about what matplotlib can do, a great option is to have a look at the matplotlib gallery, which can be found at http://matplotlib.org/gallery.html. A good way to get started is to find a figure here that sort of looks like what you want, copy the code, and modify it for your own needs.
Have a look at the matplotlib gallery. If find a cool looking figure you can copy the code into a code line. You can of course do this manually but you can also use IPython "load magic" Type %loadpy and then the URL of the py file containing the code, and it will automatically copy it into a cell below. Run the cell with the code to see the figure. Now you can make small (or large) tweaks to get your perfect figure.
Note that some of the examples might require packages that are not installed on your machine (in particular those that make maps) - if this is the case, pick another example for the purposes of this exercise.
Hint to get the raw python url right click on the source code link towards the top and pick copy link.
In [ ]:
# %load http://matplotlib.org/mpl_examples/pylab_examples/contour_demo.py
In [ ]: