Matplotlib: How to plot subplots of unequal sizes
Sometimes we would like to focus more on some data and less on others, but still provide a visual display. The matplotlib
function gridspec
allows subplots of unequal size to be plotted on the same figure. How this function can be applied will be demonstrated using simulated data. Let’s simulate some common probability distributions of different statistics using Python’s numpy.random
module:
1 2 3 4 5 6 7 8 9 10 11 
# Import libraries
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
%matplotlib inline
# Generate data
dist_norm = np.random.normal(loc=0, scale=1, size=1000)
dist_tdis = np.random.standard_t(df=29, size=1000)
dist_fdis = np.random.f(dfnum=59, dfden=28, size=1000)
dist_chsq = np.random.chisquare(df=2, size=1000)

Lines 24. Import libraries and give each an alias.
Line 5. Include this line if using an IPython/ Jupyter notebook.
Line 8. Get 1000 samples from a normal distribution with mean 0, standard deviation 1.
Line 9. Get 1000 samples from a t distribution with 29 degrees of freedom.
Line 10. Get 1000 samples from a F distribution. The F distribution typically arises in an analysis of variance (ANOVA), which compares withingroup to betweengroup variance; this comparison depends on sample size, which determines degrees of freedom in the numerator dfnum
and denominator dfden
.
Line 11. Get 1000 samples from a chisquare distribution with 2 degrees of freedom.
Now we can plot these data in a single figure, which will have 1 large subplot on the left, and a column of 3 small subplots on the right. The code to generate subplots is long but repetitive. You will get the hang of how to specify different parameters quickly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 
# Plot figure with subplots of different sizes
fig = plt.figure(1)
# set up subplot grid
gridspec.GridSpec(3,3)
# large subplot
plt.subplot2grid((3,3), (0,0), colspan=2, rowspan=3)
plt.locator_params(axis='x', nbins=5)
plt.locator_params(axis='y', nbins=5)
plt.title('Normal distribution')
plt.xlabel('Data values')
plt.ylabel('Frequency')
plt.hist(dist_norm, bins=30, color='0.30')
# small subplot 1
plt.subplot2grid((3,3), (0,2))
plt.locator_params(axis='x', nbins=5)
plt.locator_params(axis='y', nbins=5)
plt.title('t distribution')
plt.xlabel('Data values')
plt.ylabel('Frequency')
plt.hist(dist_tdis, bins=30, color='b')
# small subplot 2
plt.subplot2grid((3,3), (1,2))
plt.locator_params(axis='x', nbins=5)
plt.locator_params(axis='y', nbins=5)
plt.title('F distribution')
plt.xlabel('Data values')
plt.ylabel('Frequency')
plt.hist(dist_fdis, bins=30, color='r')
# small subplot 3
plt.subplot2grid((3,3), (2,2))
plt.locator_params(axis='x', nbins=5)
plt.locator_params(axis='y', nbins=5)
plt.title('Chisquare distribution')
plt.xlabel('Data values')
plt.ylabel('Frequency')
plt.hist(dist_chsq, bins=30, color='g')
# fit subplots and save fig
fig.tight_layout()
fig.set_size_inches(w=11,h=7)
fig_name = 'plot.png'
fig.savefig(fig_name)

Line 2. Create a figure object called fig
so we can refer to all subplots in the same figure later.
Line 4. Call the function gridspec.Gridspec
and specify an overall grid for the figure (in the background). Here, give the figure a grid of 3 rows and 3 columns.
Line 7. Call the function plt.subplot2grid()
and specify the size of the figure’s overall grid, which is 3 rows and 3 columns (3,3)
. Specify the location of the large subplot: start counting from row 0 column 0 (0,0)
and make a subplot across 2 columns and 3 rows colspan=2, rowspan=3
. (Remember, Python indexes from 0, so the 3 rows or columns will be indexed as row or column 0, 1, 2.)
Lines 813. In this subplot, do the following:
 for the x and y axes, set the number of bins to maximum of 5
 give the plot a title
 give the x and y axes titles
 plot a histogram of the data with 30 bins and set the colour
Line 16. Specify the location of the first small subplot: start counting from row 0 column 2. In this subplot, do the following (similar to above) …
Line 25. Specify the location of the second small subplot: start counting from row 1 column 2. In this subplot, do the following …
Line 34. Count from row 2 column 2, do the following …
Line 43. Give the figure a tight_layout
so that subplots are nicely spaced between each other. (Ironically, if you don’t specify this, the subplots are squeezed together even more tightly and text is overlaid.)
Lines 4446. Set figure size, give it a name and save the figure
Play around with different parameter settings for each of the distributions to see how these change the properties of the distribution. The code above produces Figure 1 below:
Summary
In Python’s matplotlib
library, the function gridspec
can be applied to plot subplots of unequal sizes by specifying an overall row and column grid for a figure, then referencing location and size of individual subplots within the figure.
Note: Another way to plot subplots of unequal sizes in Matplotlib is to specify subplot parameters in a style similar to Matlab’s plotting style. Check out this tutorial.
If I want to achieve this using matplotlib 0.99.1 (Without grid2spec), is it possible? Thank you.
LikeLiked by 1 person
Hi James, I have not tested the code in older versions of Matplotlib but there is a simpler way to plot subplots of different sizes without using gridspec, explained in this post. Cheers
LikeLike
Thanks Joanna, to redirect us to this link. It’s absolutely helpful and keeps the script neat and clean. But James’ post has helped me to get a quite difficult set of subplots spanning over more than 2 rows running, while the link didn’t. Or at least I couldn’t get it running.
LikeLike
Thanks mate. Nice clear explanation.
LikeLiked by 1 person