Too much space between subplots with gridspec

Question:

I am trying to make a figure with a grid of 12 plots on the left and one larger plot on the right. The problem is that matplotlib adds far too much space between the small subplots. How can I get rid of this space?

import matplotlib.pyplot as plt

fig = plt.figure(constrained_layout=True)
gs = fig.add_gridspec(4, 5)

ax0 = fig.add_subplot(gs[0, 0])
ax0.set_ylabel(r'$a_t$')
ax0.tick_params(labelbottom=False)
ax0.set_title(r'$beta = 0$')
ax1 = fig.add_subplot(gs[1, 0], sharex=ax0)
ax1.set_ylabel(r'$x_t$')
ax1.tick_params(labelbottom=False)

ax = fig.add_subplot(gs[0, 1], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 0.5$')
ax = fig.add_subplot(gs[1, 1], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False, labelbottom=False)

ax = fig.add_subplot(gs[0, 2], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 1$')
ax = fig.add_subplot(gs[1, 2], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False, labelbottom=False)

ax = fig.add_subplot(gs[2, 0], sharex=ax0, sharey=ax0)
ax.set_ylabel(r'$a_t$')
ax.tick_params(labelbottom=False)
ax.set_title(r'$beta = 1.5$')
ax = fig.add_subplot(gs[3, 0], sharex=ax0, sharey=ax1)
ax.set_ylabel(r'$x_t$')

ax = fig.add_subplot(gs[2, 1], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 2$')
ax = fig.add_subplot(gs[3, 1], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False)

ax = fig.add_subplot(gs[2, 2], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 3$')
ax = fig.add_subplot(gs[3, 2], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False)

ax = fig.add_subplot(gs[:, 3:])

This is what it looks like:

Too much space

This is what it looks like without the last line (ax = fig.add_subplot(gs[:, 3:])):

Better, but missing the big plot

The plots are much closer togeher. That’s what I want it to look like, but of course with the big plot in the right.

Asked By: Onno Eberhard

||

Answers:

If you want to try subfigures, something like

fig0 = plt.figure(constrained_layout=True)

sfigs = fig0.subfigures(1, 2, width_ratios=[3, 2])

fig = sfigs[0]
gs = fig.add_gridspec(4, 3)
...
# code as before
...
ax = sfigs[1].subplots()

works fine, though note the top spine doesn’t line up because there is no title on the righthand subplot

enter image description here

Answered By: Jody Klymak

A good solution seems to be Nested Gridspecs. The result looks very similar to Jody Klymak’s solution with subfigures; I’m not sure if there is a reason to prefer one above the other.

Nested Gridspec

The code:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig = plt.figure(constrained_layout=True, figsize=(6, 3))
gs0 = fig.add_gridspec(1, 2, width_ratios=(3, 2))
gs = gridspec.GridSpecFromSubplotSpec(4, 3, subplot_spec=gs0[0])

ax0 = fig.add_subplot(gs[0, 0])
ax0.set_ylabel(r'$a_t$')
ax0.tick_params(labelbottom=False)
ax0.set_title(r'$beta = 0$')
ax1 = fig.add_subplot(gs[1, 0], sharex=ax0)
ax1.set_ylabel(r'$x_t$')
ax1.tick_params(labelbottom=False)

ax = fig.add_subplot(gs[0, 1], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 0.5$')
ax = fig.add_subplot(gs[1, 1], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False, labelbottom=False)

ax = fig.add_subplot(gs[0, 2], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 1$')
ax = fig.add_subplot(gs[1, 2], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False, labelbottom=False)

ax = fig.add_subplot(gs[2, 0], sharex=ax0, sharey=ax0)
ax.set_ylabel(r'$a_t$')
ax.tick_params(labelbottom=False)
ax.set_title(r'$beta = 1.5$')
ax = fig.add_subplot(gs[3, 0], sharex=ax0, sharey=ax1)
ax.set_ylabel(r'$x_t$')

ax = fig.add_subplot(gs[2, 1], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 2$')
ax = fig.add_subplot(gs[3, 1], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False)

ax = fig.add_subplot(gs[2, 2], sharex=ax0, sharey=ax0)
ax.tick_params(labelleft=False, labelbottom=False)
ax.set_title(r'$beta = 3$')
ax = fig.add_subplot(gs[3, 2], sharex=ax0, sharey=ax1)
ax.tick_params(labelleft=False)

gs = gridspec.GridSpecFromSubplotSpec(1, 1, subplot_spec=gs0[1])
ax = fig.add_subplot(gs[0, 0])
Answered By: Onno Eberhard