Search code examples
pythonmatplotlibmatplotlib-gridspec

How to modify width between subplots with gridspec


when I create a figure with subplots in python using matplotlib and gridspec, I have the problem that I can't adjust the width of the space between subplots appropriately.

While a variation of the hspace parameter works fine already in a range of 0 to 1, I have to vary wspace up to 100 in order to get some movement in there and I can't set it high enough so that the y-axis label is not touching the subplot to its left.

Here is a minimal working smaple. I also tried varying the width in figsize, but that just made my subplots broader/smaller and didn't influence the space between.

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

fig = plt.figure(figsize=([7,4]))

gs = gridspec.GridSpec(2,18)
gs.update(wspace=100., hspace=0.3)

ax1 = plt.subplot(gs[0,:6])
ax1.set_ylabel('ylabel', labelpad=0, fontsize=12)

ax2 = plt.subplot(gs[0,6:12])
ax2.set_ylabel('ylabel', labelpad=0, fontsize=12)

ax3 = plt.subplot(gs[0,12:18])
ax3.set_ylabel('ylabel', labelpad=0, fontsize=12)

ax4 = plt.subplot(gs[1,3:9])
ax4.set_ylabel('ylabel', labelpad=0, fontsize=12)

ax5 = plt.subplot(gs[1,9:15])
ax5.set_ylabel('ylabel', labelpad=0, fontsize=12)

One workaround would be to increase the number of cells of the gridspec and put empty cells between the subplots, but I am wondering why varying wspace does not do the job?

Working with python 2.7 and matplotlib 1.5.1 on a linux cluster.


Solution

  • I don't think a number like 100 makes any sense at all. That would mean the space should be 100 times as large as the subplot.

    The figure is 7 inch wide. Taking into account the left margin of 12.5% and the right margin of 10%, you're left with 5.425 inch to distrubite to the subplots. Let's call that size s.

    Having n subplots (or grid cells), the equation that determines the space and cell size is

     s = n*axw + (n-1)*axw*wspace 
    

    with axw being the size of a cell in inches. We may use this formula to visualize for the given figure size and a bunch of numbers of cells (n), the axes size and the spacing in inches depending on the wspace.

    enter image description here

    We observe that there is a maximum size for axes and spacing. The higher the number of cells, the lower that maximum possible size. Also, the larger the axes, the smaller the spacing and vice versa. This explains nicely why there is no difference between wspace=10 and 100.

    I have marked a size of 0.6 inches in the plot. Suppose this is the minimal spacing you need in inches such that the labels don't overlap. From the plot we can read that this is only ever possible with n equal 9 or smaller. A grid of 18 cells will hence not ever allow for nonoverlapping labels in that given figure size.

    Appart from using a larger figure, you may of course reduce the number of cells.

    Since any number used in the example from the question is a multiple of 3, the grid can be reduced to a smaller grid with the same properties. In that case the space is correctly set. E.g. for wspace=1.5 (i.e. 50% larger than the cell size)

    import matplotlib.pyplot as plt
    import matplotlib.gridspec as gridspec
    
    fig = plt.figure(figsize=([7,4]))
    
    gs = gridspec.GridSpec(2,6)
    gs.update(wspace=1.5, hspace=0.3)
    
    ax1 = plt.subplot(gs[0,:2])
    ax1.set_ylabel('ylabel', labelpad=0, fontsize=12)
    
    ax2 = plt.subplot(gs[0,2:4])
    ax2.set_ylabel('ylabel', labelpad=0, fontsize=12)
    
    ax3 = plt.subplot(gs[0,4:6])
    ax3.set_ylabel('ylabel', labelpad=0, fontsize=12)
    
    ax4 = plt.subplot(gs[1,1:3])
    ax4.set_ylabel('ylabel', labelpad=0, fontsize=12)
    
    ax5 = plt.subplot(gs[1,3:5])
    ax5.set_ylabel('ylabel', labelpad=0, fontsize=12)
    
    plt.show()
    

    enter image description here