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:
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
Just specify vmin=0, vmax=1 . By default, imshow normalizes the data to its min and max. You can control this with either the vmin and vmax arguments or with the norm argument (if you want a non-linear scaling).
Use with GridSpectight_layout method (the pyplot api pyplot. tight_layout also works). You may provide an optional rect parameter, which specifies the bounding box that the subplots will be fit inside. The coordinates must be in normalized figure coordinates and the default is (0, 0, 1, 1).
To change figure size of more subplots you can use plt. subplots(2,2,figsize=(10,10)) when creating subplots.
The easiest way to display multiple images in one figure is use figure(), add_subplot(), and imshow() methods of Matplotlib. The approach which is used to follow is first initiating fig object by calling fig=plt. figure() and then add an axes object to the fig by calling add_subplot() method.
It's not perfectly clear what your desired outcome is.
You may use automatic aspect on the image
ax.imshow(z, aspect="auto")
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)
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)
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With