Python 使用 matplotlib imshow 和 scatter 获得相同的子图大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44654421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:19:27  来源:igfitidea点击:

Getting the same subplot size using matplotlib imshow and scatter

pythonmatplotlib

提问by DavidG

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:

我正在尝试matplotlib.imshow在同一图中绘制图像(使用)和散点图。尝试此操作时,图像看起来比散点图小。小示例代码如下所示:

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)

如何让两个 sublpots 具有相同的高度?(和我想的宽度)

I have tried using gridspecas shown in thisanswer:

我已尝试使用gridspec答案所示:

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 imshowand a scatterplot appear the same size in a figure without manually changing the axes sizes?

有没有一种方法,使imshowscatter情节出现在图中相同的尺寸,而无需手动更改轴的尺寸?

I am using Python 2.7 and matplotlib 2.0.0

我正在使用 Python 2.7 和 matplotlib 2.0.0

回答by ImportanceOfBeingErnest

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 hereComplete 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 answerfor using the subplot parameters to achieve a certain aspect.

    • If you want to use mpl_toolkitsand make your hands dirty, this answerwould be a good read.

  1. 您可以在图像上使用自动外观

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

    在此处输入图片说明

  2. 或者您可以根据其轴限制设置线图的方面,使其与图像大小相同(如果图像具有相同的 x 和 y 大小)

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

    在此处输入图片说明完整代码:

    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()
    

    如果图像没有相等的界限(不是正方形),仍然需要除以图像的纵横比:

    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. 更复杂的解决方案:

    • 这个答案使用子图参数来实现某个方面。

    • 如果你想使用mpl_toolkits并弄脏你的手,这个答案将是一个很好的阅读。

回答by Tonechas

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:

我遇到了同样的问题,并在 SO 中问了一个非常相似的问题。@ImportanceOfBeingErnest 提出的解决方案对我来说很有吸引力,但为了完整起见,我想提一个非常简单的解决方法,在我的问题被标记为完全重复之前,我被建议应用(归功于@Yilun Zhang)一:

The problem is that the plot region height is too large and this is leaving empty placein 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

期望的结果

回答by mauve

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.

我明确地选择在我的图中将有 2 个子图,并且该图将被选择为高值,每个子图的宽度大约是该尺寸的一半,并且子图的纵横比为 1(即,它们都是方形的)。图形大小是强制间距的特定比率。