When I first learned Python three years ago, I was often finding myself having to lookup the same thing again and again for Matplotlib. This was back pre-2.0 when there was even more issues (e.g. plotting NaNs
with masked arrays).
Some of this is super simple, some of it is more advanced. It is just my go-to reference
import numpy as np
import matplotlib as mpl
import matplotlib.pylab as plt
#%matplotlib inline # Display inline -- May not be needed on newer platforms
import sys
print('Matplotlib Version: ' + mpl.__version__)
print('NumPy Version: ' + np.version.full_version)
print('Python Version: ' + sys.version)
import datetime
now = datetime.datetime.now().isoformat()
print('Ran on ' + now)
Matplotlib Version: 2.2.3 NumPy Version: 1.15.1 Python Version: 3.7.0 (default, Jun 28 2018, 07:39:16) [Clang 4.0.1 (tags/RELEASE_401/final)] Ran on 2018-09-18T11:15:45.456807
With few exception, all examples use the object-oriented interface via plt.subplots()
. In general, there is full parity between pyplot
and the object-oriented interface. My personal opinion is plt.(...)
for quick-and-dirty and then use ax.(...)
when I want more control.
With labels, etc. The code exPlot
builds the basics with the set configurations
x = np.linspace(0,2*np.pi,10**3)
y = np.sin(x) + np.cos(x)
def exPlot(isTeX=False):
fig,ax = plt.subplots(1,1,figsize=(3,3),dpi=100,num=1)
ax.plot(x,y,'-k')
ax.set_xlabel(r'x label with math (ex: $x^2$)')
if not isTeX:
ax.set_ylabel(r'y label with non-math math (ex: $\mathregular{{x^2}}$)') # Doesn't work for LaTeX render
plt.rc('font', family='sans-serif') # These are the defaults
plt.rc('text', usetex=False)
exPlot()
plt.rc('font', family='serif')
exPlot()
... then reset
plt.rc('font', family='serif')
plt.rc('text', usetex=True)
exPlot(isTeX=True)
plt.rc('font', family='sans-serif')
plt.rc('text', usetex=False)
fig,(ax1,ax2) = plt.subplots(1,2,figsize=(7,3),dpi=100,num=1)
# Regular
ax1.plot(x,1e4*y)
# Scientific
ax2.plot(x,1e4*y)
from matplotlib import ticker
formatter = ticker.ScalarFormatter(useMathText=True)
formatter.set_scientific(True)
formatter.set_powerlimits((-1,1))
ax2.yaxis.set_major_formatter(formatter)
def subdemo(axes):
for ii,ax in enumerate(axes.ravel()):
ax.plot(x,10**(ii)*y,'-k')
ax.yaxis.set_major_formatter(formatter) # Will always be the last one
fig,axes = plt.subplots(2,2,figsize=(7,3),dpi=100,num=1)
subdemo(axes)
This is the preffered way to do it
fig,axes = plt.subplots(2,2,figsize=(7,3),dpi=100,num=1)
subdemo(axes)
fig.tight_layout()
This example is not designed to look good. It is to show the results.
This comes from http://stackoverflow.com/a/6541482
fig,axes = plt.subplots(2,2,figsize=(7,3),dpi=100,num=1)
subdemo(axes)
fig.subplots_adjust(hspace=0.45,wspace=0.35)
## All Options w/ examples
# left = 0.125 # the left side of the subplots of the figure
# right = 0.9 # the right side of the subplots of the figure
# bottom = 0.1 # the bottom of the subplots of the figure
# top = 0.9 # the top of the subplots of the figure
# wspace = 0.2 # the amount of width reserved for blank space between subplots
# hspace = 0.2 # the amount of height reserved for white space between subplots
fig,axes = plt.subplots(2,2,figsize=(7,3),dpi=100,
sharex=True)
subdemo(axes)
fig.tight_layout()
You can also share the y
axis, but it won't look good for this since they are different scales so this won't look good
fig,axes = plt.subplots(2,2,figsize=(7,3),dpi=100,
sharex=True,sharey=True)
subdemo(axes)
fig.tight_layout()
There are a few ways to do this.
gridspec
-- General purposegridspec
¶Based on http://matplotlib.org/users/gridspec.html. You seem to have to rely on the plt
tools to make all of the axes
fig = plt.figure()
ax = [None for _ in range(6)]
ax[0] = plt.subplot2grid((3,4), (0,0), colspan=4)
ax[1] = plt.subplot2grid((3,4), (1,0), colspan=1)
ax[2] = plt.subplot2grid((3,4), (1,1), colspan=1)
ax[3] = plt.subplot2grid((3,4), (1,2), colspan=1)
ax[4] = plt.subplot2grid((3,4), (1,3), colspan=1,rowspan=2)
ax[5] = plt.subplot2grid((3,4), (2,0), colspan=3)
for ix in range(6):
ax[ix].set_title('ax[{}]'.format(ix))
fig.tight_layout()
This example will be less complex to make life easier... In this case, you create the axes from the parent fig
fig = plt.figure()
ax = [None for _ in range(3)]
ax[0] = fig.add_axes([0.1,0.1,0.9,0.4]) # Bottom
ax[1] = fig.add_axes([0.15,0.6,0.25,0.6]) # They do not *need* to be in a grid
ax[2] = fig.add_axes([0.5,0.6,0.4,0.3])
for ix in range(3):
ax[ix].set_title('ax[{}]'.format(ix))
# fig.tight_layout() # does not work with this method
Can also do grids but harder (though not impossible) to do spanning
fig = plt.figure()
ax = [None for _ in range(3)]
ax[0] = fig.add_subplot(2,2,1)
ax[1] = fig.add_subplot(2,2,2)
ax[2] = fig.add_subplot(2,2,3)
for ix in range(3):
ax[ix].set_title('ax[{}]'.format(ix))
fig.tight_layout()
fig,axes = plt.subplots(2,2)
ax = axes[1,1]
ax.set_frame_on(False)
ax.set_xticks([])
ax.set_yticks([])
fig.tight_layout()
fig,axes = plt.subplots(3,3,sharex=True,sharey=True)
np.random.seed(282)
X = np.random.normal(size=(30,3))
import itertools
for ix,iy in itertools.product(range(3),range(3)):
ax = axes[ix,iy]
ax.plot(X[:,ix],X[:,iy],'ko')
for ax in axes[-1,:]:
ax.set_xlabel('x')
for ax in axes[:,0]:
ax.set_ylabel('y')
#fig.tight_layout(h_pad=0,w_pad=0)
fig.subplots_adjust(hspace=0,wspace=0)
fig = plt.figure()
axes = []
np.random.seed(282)
X = np.random.normal(size=(30,3))
import itertools
for ii,(ix,iy) in enumerate(itertools.combinations([0,1,2],2)):
ax = fig.add_subplot(2,2,2*ix+iy)
ax.plot(X[:,ix],X[:,iy],'ko')
axes.append(ax)
#fig.tight_layout(h_pad=0,w_pad=0)
fig.subplots_adjust(hspace=0,wspace=0)
np.random.seed(362423)
A = np.random.uniform(size=(6,8))
fig,(ax1,ax2,ax3,ax4) = plt.subplots(1,4,figsize=(9,3),dpi=100)
def plotEX(ax,**kw):
ax.pcolormesh(A,**kw)
plotEX(ax1)
plotEX(ax2,cmap=plt.cm.Spectral_r)
plotEX(ax3,cmap=plt.cm.Spectral_r,edgecolor='k')
plotEX(ax4,cmap=plt.cm.Spectral_r,shading='gouraud')
fig.tight_layout()
The size of the figure was selected to show the problem with scale
Also, since this invokes fig
, it doesn’t play nice with subplots
fig,ax = plt.subplots(1,1,figsize=(3,5),dpi=100)
pl = ax.pcolormesh(A,cmap = plt.cm.Spectral_r,edgecolor='k')
ax.axis('image')
fig.colorbar(pl)
<matplotlib.colorbar.Colorbar at 0x110eac828>
This example scaled the colorbar. It also plays nicely with subplots (not demoed)
fig,ax = plt.subplots(1,1,figsize=(3,5),dpi=100)
pl = ax.pcolormesh(A,cmap = plt.cm.Spectral_r,edgecolor='k')
ax.axis('image')
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
cbar = fig.colorbar(pl,cax=cax)
fig,ax = plt.subplots(1,1,figsize=(3,5),dpi=100)
pl = ax.pcolormesh(A,cmap = plt.cm.Spectral_r,edgecolor='k',vmin=-1,vmax=2.2)
ax.axis('image')
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
cbar = fig.colorbar(pl,cax=cax)
cbar.set_ticks(np.linspace(-1,2.2,6))