Search code examples
pythonmatplotlibsubplotmatplotlib-gridspec

Changing the GridSpec properties after generating the subplots


Suppose something comes up in my plot that mandates that I change the height ratio between two subplots that I've generated within my plot. I've tried changing GridSpec's height ratio to no avail.

import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

fig = plt.figure()
gs = GridSpec(2, 1, height_ratios=[2, 1])

ax1 = fig.add_subplot(gs[0])
ax1 = fig.axes[0]
ax2 = fig.add_subplot(gs[1])
ax2 = fig.axes[1]

ax1.plot([0, 1], [0, 1])
ax2.plot([0, 1], [1, 0])

gs.height_ratios = [2, 5]

The last line has no effect on the plot ratio.

In my actual code, it is not feasible without major reworking to set the height_ratios to 2:5 ahead of time.

How do I get this to update like I want?


Solution

  • The axes of relevant subplots can be manipulated and adjusted to get new height ratios.

    import matplotlib.pyplot as plt
    from matplotlib.gridspec import GridSpec
    
    fig = plt.figure()
    gs = GridSpec(2, 1, height_ratios=[2, 1]) #nrows, ncols
    
    ax1 = fig.add_subplot(gs[0])
    ax1 = fig.axes[0]
    ax2 = fig.add_subplot(gs[1])
    ax2 = fig.axes[1]
    
    ax1.plot([0, 1], [0, 1])
    ax2.plot([0, 1], [1, 0])
    
    # new height ratio: 2:5 is required for the 2 subplots
    rw, rh = 2, 5
    
    # get dimensions of the 2 axes
    box1 = ax1.get_position()
    box2 = ax2.get_position()
    # current dimensions
    w1,h1 = box1.x1-box1.x0, box1.y1-box1.y0
    w2,h2 = box2.x1-box2.x0, box2.y1-box2.y0
    top1 = box1.y0+h1
    #top2 = box2.y0+h2
    full_h = h1+h2   #total height
    
    # compute new heights for each axes
    new_h1 = full_h*rw/(rw + rh)
    new_h2 = full_h*rh/(rw + rh)
    
    #btm1,btm2 = box1.y0, box2.y0
    new_bottom1 = top1-new_h1
    
    # finally, set new location/dimensions of the axes
    ax1.set_position([box1.x0, new_bottom1, w1, new_h1])
    ax2.set_position([box2.x0, box2.y0, w2, new_h2])
    
    plt.show()
    

    The output for ratio: (2, 5):

    2x5

    The output for (2, 10):

    2x10