Getting the same subplot size using matplotlib imshow and scatter

It's not perfectly clear what your desired outcome is.

  1. You may use automatic aspect on the image

    ax.imshow(z, aspect="auto")
    

    enter image description here

  2. Or you may set the aspect of the line plot depending on its axis limits such that it gets the same size as the image (in case the image has equal x and y sizes)

    asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
    ax2.set_aspect(asp)
    

    enter image description here Complete code:

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.linspace(0,10,20)
    y = np.sin(x)
    z = np.random.rand(100,100)
    
    fig, (ax, ax2) = plt.subplots(ncols=2)
    
    ax.imshow(z)
    ax2.plot(x,y, marker=".")
    
    asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
    ax2.set_aspect(asp)
    
    plt.show()
    

    If the image does not have equal limits (is not square), one still needs to divide by the aspect of the image:

    asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
    asp /= np.abs(np.diff(ax1.get_xlim())[0] / np.diff(ax1.get_ylim())[0])
    ax2.set_aspect(asp)
    
  3. More sophisticated solutions:

    • This answer for using the subplot parameters to achieve a certain aspect.

    • If you want to use mpl_toolkits and make your hands dirty, this answer would be a good read.


I had the same problem and asked a very similar question in SO. The solution proposed by @ImportanceOfBeingErnest worked like a charm for me, but for completeness, I'd like to mention a pretty simple workaround I was suggested to apply (credit to @Yilun Zhang) before my question was marked as an exact duplicate of this one:

The problem is that the plot region height is too large and this is leaving empty place in the image.

If you change your code to:

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

then you get the desired outcome:

Desired outcome


Here's some code I use:

fig, axis_array = plt.subplots(1, 2, figsize=(chosen_value, 1.05 * chosen_value / 2),
                               subplot_kw={'aspect': 1})

I'm explicitly selecting that there will be 2 sub plots in my figure, and that the figure will be chosen_value tall and each subplot will be about half that size wide, and that the subplots will have an aspect ratio of 1 (i.e., they will both be square). The figure size is a specific ratio which forces the spacing.


For those sharing the y-axis across both plots, setting constrained_layout to True may help.