Python 如何在matplotlib中设置纵横比?

Python 如何在matplotlib中设置纵横比?,python,matplotlib,Python,Matplotlib,我正在尝试制作一个正方形的图(使用imshow),即纵横比为1:1,但我做不到。这些都不起作用: import matplotlib.pyplot as plt ax = fig.add_subplot(111,aspect='equal') ax = fig.add_subplot(111,aspect=1.0) ax.set_aspect('equal') plt.axes().set_aspect('equal') 似乎这些调用只是被忽略了(matplotlib经常出现这个问题)。您应

我正在尝试制作一个正方形的图(使用imshow),即纵横比为1:1,但我做不到。这些都不起作用:

import matplotlib.pyplot as plt

ax = fig.add_subplot(111,aspect='equal')
ax = fig.add_subplot(111,aspect=1.0)
ax.set_aspect('equal')
plt.axes().set_aspect('equal')

似乎这些调用只是被忽略了(matplotlib经常出现这个问题)。

您应该尝试使用figaspect。它对我有用。从文档中:

创建具有指定纵横比的地物。如果arg是一个数字,则使用该纵横比。>如果arg是数组,则figaspect将 确定适合阵列的图形的宽度和高度 保持纵横比。图形宽度、高度(英寸)为 返回。确保创建与和高度相等的轴,例如

用法示例:

编辑:我不确定你在找什么。上面的代码更改画布(打印大小)。如果要更改图形的matplotlib窗口的大小,请使用:

In [68]: f = figure(figsize=(5,1))

这确实会产生一个5x1(wxh)的窗口。

魅力的三倍。我猜这是一个bug,并表明它已在最新版本中修复。我有版本0.99.1.1,并创建了以下解决方案:

import matplotlib.pyplot as plt
import numpy as np

def forceAspect(ax,aspect=1):
    im = ax.get_images()
    extent =  im[0].get_extent()
    ax.set_aspect(abs((extent[1]-extent[0])/(extent[3]-extent[2]))/aspect)

data = np.random.rand(10,20)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data)
ax.set_xlabel('xlabel')
ax.set_aspect(2)
fig.savefig('equal.png')
ax.set_aspect('auto')
fig.savefig('auto.png')
forceAspect(ax,aspect=1)
fig.savefig('force.png')
这是‘force.png’:

下面是我不成功的尝试,但希望能提供信息

第二个答案:

我下面的“原始答案”有些过分,因为它做了一些类似于轴的事情。set_aspect()。我想您应该使用轴。设置方向(“自动”)。我不明白为什么会出现这种情况,但它为我生成了一个方形图像图,例如以下脚本:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.rand(10,20)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data)
ax.set_aspect('equal')
fig.savefig('equal.png')
ax.set_aspect('auto')
fig.savefig('auto.png')
生成具有“相等”纵横比的图像打印: 还有一个具有“自动”纵横比:

下面“原始答案”中提供的代码为显式控制的纵横比提供了一个起点,但一旦调用了imshow,它似乎就会被忽略

原始答案:

下面是一个例程示例,该例程将调整子地块参数,以便获得所需的纵横比:

import matplotlib.pyplot as plt

def adjustFigAspect(fig,aspect=1):
    '''
    Adjust the subplot parameters so that the figure has the correct
    aspect ratio.
    '''
    xsize,ysize = fig.get_size_inches()
    minsize = min(xsize,ysize)
    xlim = .4*minsize/xsize
    ylim = .4*minsize/ysize
    if aspect < 1:
        xlim *= aspect
    else:
        ylim /= aspect
    fig.subplots_adjust(left=.5-xlim,
                        right=.5+xlim,
                        bottom=.5-ylim,
                        top=.5+ylim)

fig = plt.figure()
adjustFigAspect(fig,aspect=.5)
ax = fig.add_subplot(111)
ax.plot(range(10),range(10))

fig.savefig('axAspect.png')
导入matplotlib.pyplot作为plt
def调整FIGASPECT(图,纵横比=1):
'''
调整子批次参数,使图形具有正确的
纵横比。
'''
xsize,ysize=图获取大小英寸()
minsize=min(xsize,ysize)
xlim=.4*minsize/xsize
ylim=.4*minsize/ysize
如果方面<1:
xlim*=方面
其他:
ylim/=方面
图子批次调整(左=.5-xlim,
右=.5+xlim,
底部=.5-ylim,
顶部=.5+ylim)
图=plt.图()
调整FIGASPECT(图,纵横比=.5)
ax=图添加_子批次(111)
ax.绘图(范围(10),范围(10))
图savefig('axAspect.png'))
这会产生如下图形:


我可以想象,如果您在图中有多个子图,您会希望将y和x子图的数量作为关键字参数(默认为每个1)包含到提供的例程中。然后使用这些数字和
hspace
wspace
关键字,可以使所有子地块具有正确的纵横比。

您正在运行的
matplotlib
版本是什么?我最近不得不升级到
1.1.0
,有了它,
add_subplot(111,aspect='equal')
对我很有效。

这个答案是基于Yann的答案。它将设置线性或对数绘图的纵横比。我使用了来自的附加信息来测试轴是否为对数刻度

def forceAspect(ax,aspect=1):
    #aspect is width/height
    scale_str = ax.get_yaxis().get_scale()
    xmin,xmax = ax.get_xlim()
    ymin,ymax = ax.get_ylim()
    if scale_str=='linear':
        asp = abs((xmax-xmin)/(ymax-ymin))/aspect
    elif scale_str=='log':
        asp = abs((scipy.log(xmax)-scipy.log(xmin))/(scipy.log(ymax)-scipy.log(ymin)))/aspect
    ax.set_aspect(asp)

显然,您可以使用任何版本的
log
,我使用了
scipy
,但是
numpy
math
应该可以。在获得上述答案多年的成功后,我发现这种方法不再有效,但我确实在

当然,以上作者(他可能更愿意在这里发表文章)完全归功于此,相关行如下:

ratio = 1.0
xleft, xright = ax.get_xlim()
ybottom, ytop = ax.get_ylim()
ax.set_aspect(abs((xright-xleft)/(ybottom-ytop))*ratio)
该链接还清晰地解释了matplotlib使用的不同坐标系


感谢收到的所有优秀答案,尤其是@Yann's,它将继续成为赢家。

使用plt.gca()获取当前轴并设置纵横比的简单选项

        plt.gca().set_aspect('equal')

代替您的最后一行

谢谢-在更改画布的纵横比时,它确实有一些效果:更具体地说,我需要更改图形本身的纵横比,但执行以下操作(apols格式化…):fig=plt.fig(figsize=(plt.figaspect(2.0)))是否尝试过
ax.axis('equal')
,偶然正如大家所说,您所做的应该是可行的,但是
ax.axis
可能是另一种解决方法。对于
get\u images
是空列表的情况(就像
ax.plot([0,1],[0,2])
,你可以使用
get_xlim
get_ylim
在我看来,如果使用logscale,这将不起作用。我添加了一个测试并处理该问题的答案。请随意将其合并到你的答案中,然后我将删除我的答案。外观看起来不平等的原因是因为相等的外观意味着视觉距离x中的ce将与y相同。如果图像是正方形,但绘图dx和dy不同,则这不是1:1的纵横比。在这种情况下,纵横比将是dy/dx。在
matplotlib
version
2.0.2
版本
jupyter笔记本
version
5.0.0
中对我很有效。谢谢。到的链接非常有价值。我这是一个更加完整的解释:在我看来,这是最好的答案。简单明了,绝对是最好的,我把1.0作为论据,因为这个问题是一般性的。
        plt.gca().set_aspect('equal')