Python Science Plotting
Create Panel Figure Layouts in Matplotlib with Gridspec
Use gridspec to layout your figure without the need to export multiple plots and use another program to put them together
Publication figures typically require multiple plots placed into a panelled layout to tell a story. A simple drag-and-drop method to do this could be to individually create each plot, and then use either an image-editing program or even Powerpoint to arrange plots into a full figure and save as one image. The problem with this approach; however, is that size consistency between fonts, etc. is difficult if you have to keep editing the individual plots, resizing, and moving to fit into your figure layout. One way to ensure consistent formatting amongst all of the individual plots is to directly create the panelled figure in matplotlib and export as one image. Fortunately for us, there is a powerful tool called gridspec that we can use to let matplotlib do most of the work for us. Let’s start out by creating a blank figure with a size of 10 x 10 inches:
# Import Libraries
import matplotlib.pyplot as plt
import numpy as np# Create Blank Figure
fig = plt.figure(figsize=(10, 10))Let’s say that this is the layout that we want to ultimately produce from our script:

If we want to use gridspec to our advantage, we need to simplify our layout into a grid. So to design the layout, we can think of the above figure as a 4 x 4 grid, with Plot 3 taking up the two bottom squares. We can create this initial grid as follows:
# Create 4x4 Grid
gs = fig.add_gridspec(nrows=2, ncols=2)Now that we have our grid, we can create three axes objects corresponding to the three plots in the layout above. We can index our gridspec much like we would any two-dimensional array or list. Note that for ax3 we index gs[1, :], meaning that the axis object will span the second row and both of the columns.
# Create Three Axes Objects
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[1, :])
There it is! We have the basic layout we were trying to create initially. The current layout is using 4 equally-sized squares with the default amount of spacing between them. Say we wanted a bit more control of the layout — we can start with the horizontal and vertical gaps between the individual plot in the figure, we can pass hspace (height space) and wspace (width space) as arguments. These keyword arguments take in a float value corresponding to a fraction of the average axes height and width.
# Edit gridspec to change hspace and wspace
gs = fig.add_gridspec(nrows=2, ncols=2, hspace=0.5, wspace=0.5)
As you can see, the plots are now farther spaced out because the space is being calculated as half of the average axis width and height. Now, say that we actually wanted Plot 1 to be twice the width of Plot 2, and Plot 3 to have half the height of Plot 1 and Plot 2. We can adjust this using the height_ratios and width_ratios keyword arguments. Both these arguments take a list of floats that describe the ratios of the axes heights and widths, respectively.
# Edit gridspec to change height_ratios and width_ratios
gs = fig.add_gridspec(nrows=2, ncols=2, height_ratios=[2, 1], width_ratios=[2, 1])
There we have very simply created our more complex grid layout with different heights and widths. So now, let’s use our last layout to create our final panelled figure:
# Styling
plt.style.use("seaborn-darkgrid")
plt.rcParams["font.family"] = "Avenir"
plt.rcParams["font.size"] = 16# Create Blank Figure
fig = plt.figure(figsize=(10, 10))# Create 4x4 Grid
gs = fig.add_gridspec(nrows=2, ncols=2, height_ratios=[2, 1], width_ratios=[2, 1])# Create Three Axes Objects
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[1, :])# Dummy Data
x = np.linspace(0, 2*np.pi, 1000)# Plot Data
ax1.plot(x, np.sin(x))
ax2.plot(x, np.sin(x)**2)
ax3.plot(x, np.sin(x) + np.cos(3*x))# Set axis labels
ax1.set_ylabel("y", size=20)
ax3.set_xlabel("x", size=20)
ax3.set_ylabel("y", size=20)
And there we have it! We were able to create our panelled figure very simply using gridspec in matplotlib.
Conclusion
This was a very basic introduction to using gridspec to create your panelled figures with multiple plots. You can use the settings shown in this article to create some very sophisticated layouts, even taking advantage of using blank plots in some of the grid elements to create areas of space. The gridspec.ipynb notebook from this article will be available at this Github repository.
Thank you for reading! I appreciate any feedback, and you can find me on Twitter and connect with me on LinkedIn for more updates and articles.






