Introductory Notes: Matplotlib
Preliminaries
Start by importing these Python modules
import numpy as np
import pandas as pd
from pandas import DataFrame, Series
import [Link] as plt
import matplotlib
Which Application Programming Interface?
Matplotlib: intro to the object oriented way
The two worlds of Matplotlib
There are 2 broad ways of using pyplot:
1. The first (and most common) way is not pythonic. It The Figure
relies on global functions to build and display a global Figure is the top-level container for everything on a
figure using matplotlib as a global state machine. canvas. It was obtained from the global Figure factory.
(This is an easy approach for interactive use). fig = [Link](num=None, figsize=None,
2. The second way is pythonic and object oriented. You dpi=None, facecolor=None,
obtain an empty Figure from a global factory, and edgecolor=None)
then build the plot explicitly using the methods of the num – integer or string identifier of figure
Figure and the classes it contains. (This is the best if num exists, it is selected
approach for programmatic use). if num is None, a new one is allocated
figsize – tuple of (width, height) in inches
While these notes focus on second approach, let's begin dpi – dots per inch
with a quick look at the first. facecolor – background; edgecolor – border
Iterating over the open figures
for i in plt.get_fignums():
Using matplotlib in a non-pythonic way fig = [Link](i) # get the figure
print ([Link]) # do something
1. Get some (fake) data - monthly time series
Close a figure
x = pd.period_range('1980-01-01',
[Link]([Link]) # close figure
periods=410, freq='M')
x = x.to_timestamp().to_pydatetime() [Link]() # close the current figure
y = [Link](len(x)).cumsum() [Link](i) # close figure numbered i
[Link](name) # close figure by str name
[Link]('all')# close all figures
2. Plot the data
[Link](x, y, label='FDI') An Axes or Subplot (a subclass of Axes)
An Axes is a container class for a specific plot. A figure
3. Add your labels and pretty-up the plot may contain many Axes and/or Subplots. Subplots are
[Link]('Fake Data Index') laid out in a grid within the Figure. Axes can be placed
[Link]('Date') anywhere on the Figure. There are a number of
[Link]('Index') methods that yield an Axes, including:
[Link](True)
ax = fig.add_subplot(2,2,1) # row-col-num
[Link](0.995, 0.01, 'Footnote',
ha='right', va='bottom') ax = fig.add_axes([0.1,0.1,0.8,0.8])
[Link](loc='best', framealpha=0.5,
prop={'size':'small'}) All at once
plt.tight_layout(pad=1) We can use the subplots factory to get the Figure and all
[Link]().set_size_inches(8, 4) the desired Axes at once.
fig, ax = [Link]()
4. SAVE the figure fig,(ax1,ax2,ax3) = [Link](nrows=3,
[Link]('[Link]') ncols=1, sharex=True, figsize=(8,4))
5. Finally, close the figure Iterating the Axes within a Figure
[Link]() for ax in fig.get_axes():
pass # do something
Alternatively, SHOW the figure
With IPython, follow steps 1 to 3 above then Remove an Axes from a Figure
[Link]() # Note: also closes the figure [Link](ax)
1!
!
Line plots – using [Link]() Scatter plots – using [Link]()
Single plot constructed with Figure and Axes A simple scatter plot
# --- get the data x = [Link](100)
x = [Link](0, 16, 800) y = x + [Link](100) + 10
y = [Link](x) fig, ax = [Link](figsize=(8, 3))
# --- get an empty figure and add an Axes [Link](x, y, alpha=0.5, color='orchid')
fig = [Link](figsize=(8,4)) [Link]('Example Scatter Plot')
ax = fig.add_subplot(1,1,1) # row-col-num fig.tight_layout(pad=2);
# --- line plot data on the Axes [Link](True)
[Link](x, y, 'b-', linewidth=2, [Link]('[Link]', dpi=125)
label=r'$y=\sin(x)$')
# --- add title, labels and legend, etc.
ax.set_ylabel(r'$y$', fontsize=16);
ax.set_xlabel(r'$x$', fontsize=16)
[Link](loc='best')
[Link](True)
[Link]('The Sine Wave')
fig.tight_layout(pad=1)
[Link]('[Link]', dpi=125)
Add a regression line (using statsmodels)
import [Link] as sm
x = sm.add_constant(x) # intercept
# Model: y ~ x + c
model = [Link](y, x)
fitted = [Link]()
x_pred = [Link]([Link](), [Link](), 50)
x_pred2 = sm.add_constant(x_pred)
y_pred = [Link](x_pred2)
Multiple lines with markers on a line plot [Link](x_pred, y_pred, '-',
# --- get the Figure and Axes all at once color='darkorchid', linewidth=2)
fig, ax = [Link](figsize=(8,4)) [Link]('[Link]', dpi=125)
# --- plot some lines
N = 8 # the number of lines we will plot
styles = ['-', '--', '-.', ':']
markers = list('+ox^psDv')
x = [Link](0, 100, 20)
for i in range(N): # add line-by-line
y = x + x/5*i + i
s = styles[i % len(styles)]
m = markers[i % len(markers)]
[Link](x, y,
label='Line '+str(i+1)+' '+s+m,
marker=m, linewidth=2, linestyle=s)
# --- add grid, legend, title and save
[Link](True)
[Link](loc='best', prop={'size':'large'})
[Link]('A Simple Line Plot')
[Link]('[Link]', dpi=125)
2!
!
Add confidence bands for the regression line Changing the marker size and colour
y_hat = [Link](x) N = 100
y_err = y - y_hat x = [Link](N)
mean_x = x.T[1].mean() y = [Link](N)
n = len(x) size = (([Link](N) + 1) * 8) ** 2
dof = n - fitted.df_model - 1 colours = [Link](N)
from scipy import stats fig, ax = [Link](figsize=(8,4))
t = [Link](1-0.025, df=dof) # 2-tail l = [Link](x, y, s=size, c=colours)
s_err = [Link]([Link](y_err, 2)) [Link](l)
conf = t * [Link]((s_err/(n-2))*(1.0/n + ax.set_xlim((-0.05, 1.05))
([Link]((x_pred-mean_x),2) / ax.set_ylim((-0.05, 1.05))
(([Link]([Link](x_pred,2))) - [Link]('Dramatic Scatter Plot')
n*([Link](mean_x,2)))))) fig.tight_layout(pad=2);
upper = y_pred + abs(conf) [Link](True)
lower = y_pred - abs(conf) [Link]('[Link]', dpi=125)
ax.fill_between(x_pred, lower, upper, Note: matplotlib has a huge range of colour maps in
color='#888888', alpha=0.3) addition to the default used here.
[Link]('[Link]', dpi=125)
Changing the marker symbol
fig, ax = [Link](figsize=(8,5))
markers = list('ov^<>12348sphHdD+x*|_')
Add a prediction interval for the regression line N = 10
from [Link]\ for i, m in enumerate(markers):
import wls_prediction_std x = [Link](N)
sdev, lower, upper = y = [Link](i+1, N)
wls_prediction_std(fitted, [Link](x, y, marker=m, label=m,
exog=x_pred2, alpha=0.05) s=50, c='cornflowerblue')
ax.fill_between(x_pred, lower, upper,
color='#888888', alpha=0.1) ax.set_xlim((-1,N))
[Link]('[Link]', dpi=125) ax.set_ylim((0,len(markers)+1))
[Link](loc='upper left', ncol=3,
prop={'size':'xx-large'},
shadow=True, title='Marker Legend')
ax.get_legend().get_title().set_color("red")
[Link]('Markers ' +
'(with an oversized legend)')
fig.tight_layout(pad=2);
[Link]('[Link]', dpi=125)
Note: The confidence interval relates to the location of
the regression line. The predication interval relates to
the location of data points around the regression line.
3!
!
Bar plots – using [Link]() and [Link]()
A simple bar chart
The bars in a bar-plot are placed to the right of the bar x-
axis location by default. Centred labels require a little
jiggling with the bar and label positions.
# --- get the data
N = 5
labels = list('ABCDEFGHIJKLM'[0:N])
Stacked bar
data = [Link](range(N)) +
[Link](N) # --- get some data
# --- plot the data alphas = [Link]( [23, 44, 52, 32] )
fig, ax = [Link](figsize=(8, 3.5)) betas = [Link]( [38, 49, 32, 61] )
width = 0.8; labels = ['Sydney', 'Melb', 'Canb', 'Bris']
tickLocations = [Link](N) # --- the plot
rectLocations = tickLocations-(width/2.0) fig, ax = [Link](figsize=(8, 3.5))
[Link](rectLocations, data, width, width = 0.8;
color='wheat', xlocations=[Link](range(len(alphas)+2))
edgecolor='#8B7E66', linewidth=4.0) adjlocs = xlocations[1:-1] - width/2.0
# --- pretty-up the plot [Link](adjlocs, alphas, width,
ax.set_xticks(ticks= tickLocations) label='alpha', color='tan')
ax.set_xticklabels(labels) [Link](adjlocs, betas, width,
ax.set_xlim(min(tickLocations)-0.6, label='beta', color='wheat',
max(tickLocations)+0.6) bottom=alphas)
ax.set_yticks(range(N)[1:]) # --- pretty-up and save
ax.set_ylim((0,N)) ax.set_xticks(ticks=xlocations[1:-1])
[Link](True) ax.set_xticklabels(labels)
# --- title and save [Link](True)
[Link]("Bar Plot with " + [Link](loc='best', prop={'size':'small'})
"Oversized Edges") [Link]("Stacked Nonsense")
fig.tight_layout(pad=2) fig.tight_layout(pad=2)
[Link]('[Link]', dpi=125) [Link]('[Link]', dpi=125)
Side by side bar chart Horizontal bar charts
# --- get the data Just as tick placement needs to be managed with
before = [Link]([10, 11, 9, 12]) vertical bars; so with horizontal bars (which are above
after = [Link]([11, 12, 8, 17]) the y-tick mark)
labels=['Group '+x for x in list('ABCD')] labels = ['Males', 'Females', 'Persons']
# --- the plot – left then right data = [6.3, 7.2, 6.8]
fig, ax = [Link](figsize=(8, 3.5)) width = 0.8
width = 0.4 # bar width yTickPos = [Link](len(data))
xlocs = [Link](len(before)) yBarPos = yTickPos - (width/2.0)
[Link](xlocs-width, before, width, fig, ax = [Link](figsize=(8, 3.5))
color='wheat', label='Males') [Link](yBarPos,data,width,color='wheat')
[Link](xlocs, after, width, ax.set_yticks(ticks= yTickPos)
color='#8B7E66', label='Females') ax.set_yticklabels(labels)
# --- labels, grids and title, then save ax.set_ylim((min(yTickPos)-0.6,
ax.set_xticks(ticks=range(len(before))) max(yTickPos)+0.6))
ax.set_xticklabels(labels) [Link](True)
[Link](True) ax.set_ylabel('Gender');
[Link](loc='best') ax.set_xlabel('Rate (Percent)')
ax.set_ylabel('Mean Group Result') [Link]("Horizontal Nonsense")
[Link]('Group Results by Gender') fig.tight_layout(pad=2)
fig.tight_layout(pad=1) [Link]('[Link]', dpi=125)
[Link]('[Link]', dpi=125)
4!
!
Pie Chart – using [Link]()
Plot spines
As nice as pie
# --- get some data Hiding the top and right spines
data = [Link]([5,3,4,6])
x = [Link](-[Link], [Link], 800)
labels = ['bats', 'cats', 'gnats', 'rats']
y = [Link](x)
explode = (0, 0.1, 0, 0) # explode cats
fig, ax = [Link](figsize=(8, 4))
colrs=['khaki', 'goldenrod', 'tan', 'wheat']
[Link](x, y, label='Sine', color='red')
# --- the plot
ax.set_axis_bgcolor('#e5e5e5')
fig, ax = [Link](figsize=(8, 3.5))
[Link]['right'].set_color('none')
[Link](data, explode=explode,
[Link]['top'].set_color('none')
labels=labels, autopct='%1.1f%%',
[Link]['left'].set_position(
startangle=270, colors=colrs)
('outward',10))
[Link]('equal') # keep it a circle
[Link]['bottom'].set_position(
# --- tidy-up and save
('outward',10))
[Link]("Delicious Pie Ingredients")
[Link].set_ticks_position('bottom')
[Link]('[Link]', dpi=125)
[Link].set_ticks_position('left')
# do the [Link]() after setting ticks
[Link](b=True, which='both',
color='white', linestyle='-',
linewidth=1.5)
ax.set_axisbelow(True)
[Link](loc='best', frameon=False)
[Link]('[Link]', dpi=125)
Polar – using [Link]()
Polar coordinates
# --- theta
theta = [Link](-[Link], [Link], 800)
# --- get us a Figure
fig = [Link](figsize=(8,4)) Spines in the middle
# --- left hand plot x = [Link](-[Link], [Link], 800)
ax = fig.add_subplot(1,2,1, polar=True) y = [Link](x)
r = 3 + [Link](5*theta) fig, ax = [Link](figsize=(8, 4))
[Link](theta, r) [Link](x, y, label='Sine')
ax.set_yticks([1,2,3,4]) [Link]['right'].set_color('none')
# --- right hand plot [Link]['top'].set_color('none')
ax = fig.add_subplot(1,2,2, polar=True) [Link].set_ticks_position('bottom')
r = ([Link](theta)) - ([Link](10*theta)) [Link]['bottom'].set_position((
[Link](theta, r, color='green') 'data',0))
ax.set_yticks([1,2]) [Link].set_ticks_position('left')
# --- title, explanatory text and save [Link]['left'].set_position((
[Link]('Polar Coordinates') 'data',0))
[Link](x=0.24, y=0.05, [Link](b=True, which='both',
s=r'$r = 3 + \cos(5 \theta)$') color='#888888', linestyle='-',
[Link](x=0.64, y=0.05, linewidth=0.5)
s=r'$r = \sin(\theta) - \cos(10' + [Link]('Sine')
r'\theta)$') [Link]('[Link]', dpi=125)
[Link]('[Link]', dpi=125)
5!
!
Legend to the right of the plot
N = 5
x = [Link](N)
fig, ax = [Link](figsize=(8, 3))
for j in range(5):
[Link](x, x*(j+1),
label='Line '+str(j))
box = ax.get_position() # Shrink plot
ax.set_position([box.x0, box.y0,
[Link] * 0.8, [Link]])
[Link](bbox_to_anchor=(1, 0.5),
loc='center left') # Put legend
[Link]('[Link]', dpi=125)
Legends
Legend within the plot
Use the 'loc' argument to place the legend
N = 5
x = [Link](N)
fig, ax = [Link](figsize=(8, 3))
for j in range(5):
[Link](x, x*(j+1),label='Line'+str(j))
[Link](loc='upper left')
[Link]('[Link]', dpi=125) Legend below the plot
N = 5
x = [Link](N)
fig, ax = [Link](figsize=(8, 3))
for j in range(5):
[Link](x, x*(j+1),
label='Line '+str(j))
box = ax.get_position()
ax.set_position([box.x0,
box.y0 + [Link] * 0.15,
[Link], [Link] * 0.85])
[Link](bbox_to_anchor=(0.5, -0.075),
Legend slightly outside of the plot loc='upper center', ncol=N)
N = 5 [Link]('[Link]', dpi=125)
x = [Link](N)
fig, ax = [Link](figsize=(8, 3))
for j in range(5):
[Link](x, x*(j+1),
label='Line '+str(j))
[Link](bbox_to_anchor=(1.1, 1.05))
[Link]('[Link]', dpi=125)
6!
!
Using GridSpec layouts (like list slicing)
Multiple plots on a canvas import [Link] as gs
gs = [Link](3, 3) # nrows, ncols
Using Axes to place a plot within a plot fig = [Link](figsize=(8,4))
[Link](x=0.01, y=0.01, s='Figure',
fig = [Link](figsize=(8,4)) color='#888888', ha='left',
[Link](x=0.01, y=0.01, s='Figure', va='bottom', fontsize=20)
color='#888888', ha='left', ax1 = fig.add_subplot(gs[0, :]) # row,col
va='bottom', fontsize=20) [Link](x=0.2,y=0.2,s='0, :', color='b')
# --- Main Axes ax2 = fig.add_subplot(gs[1,:-1])
ax = fig.add_axes([0.1,0.1,0.8,0.8]) [Link](x=0.2,y=0.2,s='1, :-1', color='b')
[Link](x=0.01, y=0.01, s='Main Axes', ax3 = fig.add_subplot(gs[1:, -1])
color='red', ha='left', va='bottom', [Link](x=0.2,y=0.2, s='1:, -1', color='b')
fontsize=20) ax4 = fig.add_subplot(gs[-1,0])
ax.set_xticks([]); ax.set_yticks([]) [Link](x=0.2,y=0.2, s='-1, :0', color='b')
# --- Insert Axes ax5 = fig.add_subplot(gs[-1,-2])
ax= fig.add_axes([0.15,0.65,0.2,0.2]) [Link](x=0.2,y=0.2, s='-1,:-2', color='b')
[Link](x=0.01, y=0.01, s='Insert Axes', for a in fig.get_axes():
color='blue', ha='left', va='bottom', a.set_xticks([])
fontsize=20) a.set_yticks([])
ax.set_xticks([]); ax.set_yticks([])
[Link]('An Axes within an Axes') [Link]('GridSpec Layout')
[Link]('[Link]', dpi=125) [Link]('[Link]', dpi=125)
Simple subplot grid layouts
fig = [Link](figsize=(8,4))
[Link](x=0.01, y=0.01, s='Figure', Plotting – defaults
color='#888888', ha='left',
va='bottom', fontsize=20)
Configuration files
for i in range(4): Matplotlib uses configuration files to set the defaults. So
# fig.add_subplot(nrows, ncols, num) that you can edit it, the location of the configuration file
ax = fig.add_subplot(2, 2, i+1) can be found as follows:
[Link](x=0.01, y=0.01, print (matplotlib.matplotlib_fname())
s='Subplot 2 2 '+str(i+1),
color='red', ha='left',
va='bottom', fontsize=20) Configuration settings
ax.set_xticks([]); ax.set_yticks([]) The current configuration settings
print ([Link])
ax.set_xticks([]); ax.set_yticks([])
[Link]('Subplots') Change the default settings
[Link]('[Link]', dpi=125) [Link]('figure', figsize=(8,4), dpi=125,
facecolor='white', edgecolor='white')
[Link]('axes', facecolor='#e5e5e5',
grid=True, linewidth=1.0,
axisbelow=True)
[Link]('grid', color='white', linestyle='-',
linewidth=2.0, alpha=1.0)
[Link]('xtick', direction='out')
[Link]('ytick', direction='out')
[Link]('legend', loc='best')
7!
!
Cautionary notes
This cheat sheet was cobbled together by bots roaming
the dark recesses of the Internet seeking ursine and
pythonic myths. There is no guarantee the narratives
were captured and transcribed accurately. You use
these notes at your own risk. You have been warned.
8!
!