pythonmatplotlibplotlayout

centering the bottom row of subplots in a matplotlib grid


If I have 5 plots I want to present, is it possible to have them in 2 rows, with the top row having 3 plots, the bottom row having 2 plots, but the bottom row centred?

I can plot them with 3 on the top and 2 on the bottom, but I can't work out how to centre the bottom row.

for example:

import matplotlib.pyplot as plt
fig, axs = plt.subplots(2, 3, figsize=(10,5), sharey=True)

for i in range(5):
    row,col = divmod(i,3)
    axs[row,col].plot([0, 1], [0, i])
    
fig.delaxes(axs[1,2])

plt.tight_layout()
plt.show()

gives me this plot: enter image description here

but i can't work out how to centre the bottom row.

I tried using gridspec, and creating a 2x1 grid, and then putting the top row in the top cell of the master grid, and the bottom row in the bottom cell, but that just stretched the bottom plots out so they took up the whole bottom row. Is it possible to keep all the plots the same size, but centre the bottom two?


Solution

  • Since Matplotlib v3.3 you can use subplot_mosaic

    import matplotlib.pyplot as plt
    
    # Create a mosaic where each plot is two entries wide.  Dots represent spaces.
    mosaic = """AABBCC
                .DDEE."""
    
    fig, ax_dict = plt.subplot_mosaic(mosaic, figsize=(10,5), sharey=True)
    
    for i, ax in enumerate(ax_dict.values()):
        ax.plot([0, 1], [0, i])
        
    # Turn the y-tick labels back on for the first plot of the second row.  This is
    # off by default because the plot does not span the first column of the
    # underlying GridSpec.
    ax_dict['D'].tick_params('y', labelleft=True)
    
    plt.tight_layout()
    plt.show()
    
    

    enter image description here

    Note that subplot_mosaic uses a GridSpec underneath. If you want to get hold of it for any reason you can do so from any of the axes:

    ax.get_subplotspec().get_gridspec()