Arrange matplotlib subplots in skewed grid
Using matplotlib, I would like to display multiple subplots in a grid that has a different number of columns per row, where each subplot is roughly the same size, and the subnets are arranged so that they are more or less centered, for example:
It's pretty easy to create a grid with a 2, 3, 2 s pattern gridspec
, but the problem is, gridspec
unsurprisingly, it aligns them to the grid, so the plots in rows with two plots in them are wider:
Here's the code to generate:
from matplotlib import gridspec
from matplotlib import pyplot as plt
fig = plt.figure()
arrangement = (2, 3, 2)
nrows = len(arrangement)
gs = gridspec.GridSpec(nrows, 1)
ax_specs = []
for r, ncols in enumerate(arrangement):
gs_row = gridspec.GridSpecFromSubplotSpec(1, ncols, subplot_spec=gs[r])
for col in range(ncols):
ax = plt.Subplot(fig, gs_row[col])
fig.add_subplot(ax)
for i, ax in enumerate(fig.axes):
ax.text(0.5, 0.5, "Axis: {}".format(i), fontweight='bold',
va="center", ha="center")
ax.tick_params(axis='both', bottom='off', top='off', left='off',
right='off', labelbottom='off', labelleft='off')
plt.tight_layout()
I know I can create a bunch of subplots and tweak their location by designing its geometry, but I think it might get a little complicated, so I was hoping there might be a simpler method available.
I should note that while I am using (2, 3, 2) layout as an example, I would like to do this for arbitrary collections, not just this.
source to share
The idea is usually to find a common denominator between the subheadings, i.e. the largest subplot that the desired grid can consist of, and span all subplots above a few of them to achieve the desired layout.
Here you have 3 rows and 6 columns, and each subheading is 1 row and two columns, just that the subheadings in the first row span subheadings at positions 1/2 and 3/4, and in the second row they are at positions 0/1 , 2/3, 4/5.
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(3, 6)
ax1a = plt.subplot(gs[0, 1:3])
ax1b = plt.subplot(gs[0, 3:5])
ax2a = plt.subplot(gs[1, :2])
ax2b = plt.subplot(gs[1, 2:4])
ax2c = plt.subplot(gs[1, 4:])
ax3a = plt.subplot(gs[2, 1:3])
ax3b = plt.subplot(gs[2, 3:5])
for i, ax in enumerate(plt.gcf().axes):
ax.text(0.5, 0.5, "Axis: {}".format(i), fontweight='bold',
va="center", ha="center")
ax.tick_params(axis='both', bottom='off', top='off', left='off',
right='off', labelbottom='off', labelleft='off')
plt.tight_layout()
plt.show()
source to share