Search code examples
pythonmatplotlibscalingsubplotaxes

Matplotlib set subplot axis size iteratively


There are several related questions (here, here, and here), but the suggested solutions don't work in my case.

I'm creating subplots iteratively, so I don't know ahead of time the width of each one (it gets calculated AFTER plt.subplots() is called), which means I can't set the size of each subplot when I initially create them. I would like to set the size of the subplot x axis after it has already been created.

Imagine something like:

items = [A,B,C]  #this could have any number of items in it
f,ax = plt.subplots(len(items),1, figsize=(10,10)) #figsize is arbitrary and could be anything

for i in range(len(items)):
    #calculate x and y data for current item
    #calculate width of x axis for current item
    plt.sca(ax[i])
    cax = plt.gca()
    cax.plot(x,y)
    #here is where I would like to set the x axis size
    #something like cax.set_xlim(), but for the size, not the limit

Note 1: The units don't matter, but the relative size does, so it could be size in pixels, or centimeters, or even a ratio calculated based on the relative widths.

Note 2: The width of the x axis is NOT related in this case to the x limit, so I can't just set the x limit and expect the axis to scale correctly.

Also, I'm trying to keep this code short, since it's to be shared with people unfamiliar with Python, so if the only solution involves adding a bunch of lines, it's not worth it and I'll live with incorrectly scaled axes. This is an aesthetic preference but not a requirement. Thanks!

EDIT: Here's what I'm aiming for desired subplots


Solution

  • You can create a new GridSpec specifying the height_ratios and then updating each axs position:

    import matplotlib.pyplot as plt
    from matplotlib.gridspec import GridSpec
    
    # create figure
    f, ax = plt.subplots(3, 1, figsize=(10,10))
    
    # plot some data
    ax[0].plot([1, 2, 3])
    ax[1].plot([1, 0, 1])
    ax[2].plot([1, 2, 20])
    
    # adjust subplot sizes
    gs = GridSpec(3, 1, height_ratios=[5, 2, 1])
    for i in range(3):
        ax[i].set_position(gs[i].get_position(f))
    
    plt.show()
    

    I asked a similar question before here. The use case was slightly different, but it might still be helpful.