Search code examples
pythonmatplotlibxticks

Cut a figure along the x axis while retaining scale


I need to be able to compare graphs that show the progress of several variables over time. I need to do this for different cases, where the time covered is not always the same: now the data visualised covers 5 seconds long, then 10 seconds, then 30 seconds, etc.

The problem is that Matplotlib uses the number of seconds as a guide to determine the length of the graph -- meaning that a graph covering only 5 seconds will have the same length as one covering 30 seconds. See these two examples (NB: these are separate graphs, not subplots of the same graph):

Graph covering 5 seconds

Graph covering 30 seconds

In the documentation for xlim I read that I can use it to turn autoscaling off, and I successfully did that. The upper graph now looks like this:

Graph covering 5 seconds, scaled

which is much better.

Is it now also possible to cut the graph off after 5 seconds, so that I don't have all that empty space at the end? Like this (NB: I faked this example with a graphics program and it's a little bit too small; it should be exactly 1/6 the size of the one above):

Graph covering 5 seconds, scaled and cut


Solution

  • You can do this with a GridSpec instance. There are multiple ways to achieve what you want; here I'll use 2 rows, 2 columns, and use the width_ratios kwarg to control the size of the second subplot.

    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    
    gs = fig.add_gridspec(nrows=2, ncols=2, width_ratios=(1, 5), wspace=0)
    
    ax1 = fig.add_subplot(gs[0, :])
    ax2 = fig.add_subplot(gs[1, 0])
    
    ax1.set_xlim(0, 30)
    ax2.set_xlim(0, 5)
    
    plt.show()
    

    enter image description here

    Alternatively, you could define 6 columns, with equal width ratios, and then you could add subplots at any position along the x axis:

    import matplotlib.pyplot as pet
    
    fig = plt.figure()
    
    gs = fig.add_gridspec(nrows=4, ncols=6, wspace=0, hspace=0.35)
    
    ax1 = fig.add_subplot(gs[0, :])
    ax2 = fig.add_subplot(gs[1, 0])
    ax3 = fig.add_subplot(gs[2, 3])
    ax4 = fig.add_subplot(gs[3, 2:5])
    
    ax1.set_xlim(0, 30)
    ax2.set_xlim(0, 5)
    ax3.set_xlim(15, 20)
    ax4.set_xlim(10, 25)
    
    
    plt.show()
    

    enter image description here