tight_layout() reserves ylabel and yticklabels space even when disabled

I have a 2*4 subplots figure, with half of the ylabel and yticklabels disabled. Unfortunately, tight_layout() does not remove the extra white space which corresponds to the area where the ylabel and yticklabels would appear if they were not disabled. The ylabel and yticklabels are removed because I would like to have 4 pairs of comparison subplots. The plot looks something like this.

enter image description here

I am looking for an efficient way to remove the extra white space. In fact, I would like each pair of plots to be next to each other with no space at all. Here is an working example.

import matplotlib.pyplot as plt

fig, ((ax0, ax1, ax2, ax3), (ax4, ax5, ax6, ax7)) = plt.subplots(2, 4, figsize=(8, 4))
axs = [ax0, ax1, ax2, ax3, ax4, ax5, ax6, ax7]

for i in range(4):
    axs[2*i].set_ylabel('parameter '+str(i))
    axs[2*i+1].set_yticklabels([])

plt.tight_layout()
plt.show()

The code should yield the above plot. Any tips would be appreciated. Many thanks!

Answer

You can do it by having two subgrids and forcing a null distance between the axis (I followed this tutorial). The wspace parameter is described here.

import matplotlib.pyplot as plt

fig = plt.figure(constrained_layout=False) # you must disable automatic spacing
gs = fig.add_gridspec(1, 2, figure=fig)

gs0 = gs[0].subgridspec(2, 2, wspace=0.0)
gs1 = gs[1].subgridspec(2, 2, wspace=0.0)

axs = [[],[]]
for i in range(2):
    for j in range(2):
        axs[0].append(fig.add_subplot(gs0[i, j]))
        axs[1].append(fig.add_subplot(gs1[i, j]))

axs = [*axs[0],*axs[1]]

for i in range(4):
    axs[2*i].set_ylabel('parameter ' + str(i))
    axs[2*i+1].set_yticklabels([])

Sample image with the use of gridspec and subgridspec

Since the automatic spacing is disabled, you may have to play with axis and figure properties to adapt the position of the axis, labels, etc.

A partial (distance won’t be null, but may be interesting for other users), more elegant solution is to use constrained_layout when creating the figure. More info in matplotlib’s documentation.

import matplotlib.pyplot as plt

fig, axs = plt.subplots(
    2, 4,
    figsize=(8, 4),
    constrained_layout=True,
    )

axs = axs.reshape([8])
for i in range(4):
    axs[2*i].set_ylabel('parameter '+str(i))
    axs[2*i+1].set_yticklabels([])

# plt.tight_layout() # not necessary
plt.show()

Sample image with the use of constrained layout