How to preserve figsize when using gridspec in matplotlib?

I use gridspec to plot a figure with 5 subplots (1 in row 1 and 2 in rows 2-3). No matter which figure size I specify, it stretches it vertically so the subplots turn out very skinny (example figure attached). I played with 1515, 1520, 20*25 and it just never matched the dimensions. I tried it with constrained_layout and without, with subplots_adjust and without but I can’t get it right. h e l p

cm = 1/2.54
        fig = plt.figure(figsize=(25*cm, 27*cm), constrained_layout=True)
        
        fontsize = 10
        gs = gridspec.GridSpec(3, 6, height_ratios=[1, 1, 1])

        # First row, two subplots
        ax1 = fig.add_subplot(gs[0, 2:3])
        ax2 = fig.add_subplot(gs[1, 1:2])
        ax3 = fig.add_subplot(gs[1, 3:4])
        ax4 = fig.add_subplot(gs[2, 1:2])
        ax5 = fig.add_subplot(gs[2, 3:4])

......


        for ax, label in zip(axes, ['a)', 'b)', 'c)', 'd)', 'e)']):
                if ax in [ax4, ax5]:
                        ax.set_xlabel('$\sigma_2$ [+1037 kg m$^{-3}$]')
                if ax in [ax1,ax2,ax4]:
                        ax.set_ylabel('Tracer concentration [%]')

                ax.tick_params(axis="x", bottom=True, top=False, labelbottom=True, labeltop=False, labelrotation=35)
                if ax in [ax1, ax2, ax4]:
                        ax.tick_params(axis="y", left=True, right=True, labelleft=True, labelright=False)
                if ax in [ax3,ax5]:
                        ax.tick_params(axis="y", left=True, right=True, labelleft=False, labelright=False)
                ax.annotate(label,
                        xy=(0.05, 135), xycoords='axes points',
                        xytext=(+0.5, -0.5), textcoords='offset fontsize',
                        fontsize='medium', verticalalignment='top', fontfamily='sans-serif',
                        bbox=dict(facecolor='white', edgecolor='none', pad=3.0))

        # plt.tight_layout()
        fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9)

Also, if I decrease the figure height, the labels overlap titles, etc, but aspect ratio of the subplots doesn’t change:

The closest to nice look I could get is this:

It it the result of figsize=(25*cm,27*cm) but it doesn’t seem to have the aspect ratio of 25*27. And I also don’t understand why it has so much white space between the subplots. I specified in grid spec that ax2, ax4 should occupy 1-2 gird “cells” horizontally but on the figure, it seems more like 0-1 grid cells.

Here’s the result of edited subplots:

``
gs = gridspec.GridSpec(3, 6, height_ratios=[1, 1, 1])

ax1 = fig.add_subplot(gs[0, 2:4])
ax2 = fig.add_subplot(gs[1, 0:2])
ax3 = fig.add_subplot(gs[1, 4:6])
ax4 = fig.add_subplot(gs[2, 0:2])
ax5 = fig.add_subplot(gs[2, 4:6])``

Still to much white space between subplots…

Possibly you need to use only 4 columns and index them like so:

cm = 1/2.54
fig = plt.figure(figsize=(15*cm, 27*cm), constrained_layout=True)

fontsize = 10
gs = gridspec.GridSpec(3, 4, height_ratios=[1, 1, 1])


# First row, two subplots
ax1 = fig.add_subplot(gs[0, 1:3])
ax2 = fig.add_subplot(gs[1, 0:2])
ax3 = fig.add_subplot(gs[1, 2:])
ax4 = fig.add_subplot(gs[2, 0:2])
ax5 = fig.add_subplot(gs[2, 2:])

This gives me:

You could then play around with the figure size to get the subplot aspect ratio that you want.

4 Likes