45

I am trying to plot an image (using matplotlib.imshow) and a scatter plot within the same figure. When trying this, the image appears smaller than the scatter plot. Small example code is shown below:

import matplotlib.pyplot as plt
import numpy as np

image = np.random.randint(100,200,(200,200))
x = np.arange(0,10,0.1)
y = np.sin(x)

fig, (ax1, ax2) = plt.subplots(1,2)
ax1.imshow(image)
ax2.scatter(x,y)

plt.show()

Which gives the following figure:

enter image description here

How can I get the two sublpots to have the same height? (and width I suppose)

I have tried using gridspec as shown in this answer:

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

ax1=fig.add_subplot(gs[0,0])
ax2=fig.add_subplot(gs[0,1])
ax1.imshow(image)
ax2.scatter(x,y)

But this gives the same result. I have also tried to adjust the subplot sizes manually by using:

fig = plt.figure()
ax1 = plt.axes([0.05,0.05,0.45,0.9])
ax2 = plt.axes([0.55,0.19,0.45,0.62])

ax1.imshow(image)
ax2.scatter(x,y)

By trial and error I can get the two subplots to the correct size, though any change in the overall figure size will mean that the subplots will no longer be the same size.

Is there a way to make imshow and a scatter plot appear the same size in a figure without manually changing the axes sizes?

I am using Python 2.7 and matplotlib 2.0.0

4 Answers 4

65

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.

Sign up to request clarification or add additional context in comments.

1 Comment

The desired outcome was simply that the two subplots were exactly the same size and stayed that way when the figure was resized. Anyway, aspect='auto' did the trick, thanks.
3

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

2 Comments

The question to ask is, how did you figure out the (14, 6) was the correct size for the two plots to have the same height?
This solution does not work in the case the left image has a colorbar.
3

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

1 Comment

This worked for me! I was creating a broken y-axis (matplotlib.org example) and wanted the size to remain unchanged.
2

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.

1 Comment

Your plot will then look like this: i.sstatic.net/fsGB2.png I don't think that this is what OP wants.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.