Search code examples
pythonmatplotlibaxisfigure

same scale of Y axis on differents figures


I try to plot different data with similar representations but slight different behaviours and different origins on several figures. So the min & max of the Y axis is different between each figure, but the scale too.

e.g. here are some extracts of my batch plotting :

enter image description here enter image description here

Does it exists a simple way with matplotlib to constraint the same Y step on those different figures, in order to have an easy visual interpretation, while keeping an automatically determined Y min and Y max ?

In others words, I'd like to have the same metric spacing between each Y-tick


Solution

  • you could use a MultipleLocator from the ticker module on both axes to define the tick spacings:

    import matplotlib.pyplot as plt
    import matplotlib.ticker as ticker
    
    fig=plt.figure()
    ax1=fig.add_subplot(211)
    ax2=fig.add_subplot(212)
    ax1.set_ylim(0,100)
    ax2.set_ylim(40,70)
    
    # set ticks every 10
    tickspacing = 10
    ax1.yaxis.set_major_locator(ticker.MultipleLocator(base=tickspacing)) 
    ax2.yaxis.set_major_locator(ticker.MultipleLocator(base=tickspacing))
    
    plt.show()
    

    enter image description here

    EDIT:

    It seems like your desired behaviour was different to how I interpreted your question. Here is a function that will change the limits of the y axes to make sure ymax-ymin is the same for both subplots, using the larger of the two ylim ranges to change the smaller one.

    import matplotlib.pyplot as plt
    import numpy as np
    
    fig=plt.figure()
    ax1=fig.add_subplot(211)
    ax2=fig.add_subplot(212)
    ax1.set_ylim(40,50)
    ax2.set_ylim(40,70)
    
    def adjust_axes_limits(ax1,ax2):
    
        yrange1 = np.ptp(ax1.get_ylim())
        yrange2 = np.ptp(ax2.get_ylim())
    
        def change_limits(ax,yr):
            new_ymin = ax.get_ylim()[0] - yr/2.
            new_ymax = ax.get_ylim()[1] + yr/2.
            ax.set_ylim(new_ymin,new_ymax)
    
        if yrange1 > yrange2:
            change_limits(ax2,yrange1-yrange2)
        elif yrange2 > yrange1:
            change_limits(ax1,yrange2-yrange1)
        else:
            pass
    
    adjust_axes_limits(ax1,ax2)
    plt.show()
    

    Note that the first subplot here has expanded from (40, 50) to (30, 60), to match the y range of the second subplot enter image description here