如何在 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 中经常遇到的问题)。

340278 次浏览

你应该试试 figaspect。它对我很有效。从文档中可以看出:

创建一个指定宽高比的图形。如果 arg 是一个数字,则使用该宽高比。如果 arg 是一个数组,则 figaspect 将确定适合数组的宽度和高度,保持宽高比。返回图形的宽度和高度(以英寸为单位)。请确保创建一个具有相等宽度和高度的轴,例如

示例用法:

  # make a figure twice as tall as it is wide
w, h = figaspect(2.)
fig = Figure(figsize=(w,h))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.imshow(A, **kwargs)


# make a figure with the proper aspect for an array
A = rand(5,3)
w, h = figaspect(A)
fig = Figure(figsize=(w,h))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.imshow(A, **kwargs)

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

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

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

这次一定能解决。我的猜测是这应该是一个错误以及在 Zhenya 的回答中提到会在最新的版本中修复它。我的版本是 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’: enter image description here

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

第二个答案:

我的“原始答案”过于复杂,因为它与 axes.set_aspect() 类似。我认为你想使用 axes.set_aspect('auto')。我不明白为什么会这样,但是它为我生成了一个正方形的图像绘图,例如这个脚本:

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

生成具有“相等”高宽比的图像情节: enter image description here 还有一个“自动”高宽比: enter image description here

下面“原始答案”中提供的代码为显式控制的高宽比提供了一个起点,但是一旦调用 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')

这就产生了这样一个数字: enter image description here

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

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

这个答案是基于杨的回答。它将设置线性或对数曲线的纵横比。我使用了来自 https://stackoverflow.com/a/16290035/2966723的附加信息来测试轴是否是对数尺度的。

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,但 numpymath应该是罚款。

经过多年的成功与上述答案,我已经发现这不工作了-但我确实找到了一个工作的解决方案的次要情节

Https://jdhao.github.io/2017/06/03/change-aspect-ratio-in-mpl

当然,上面的作者(也许可以在这里贴出来)功不可没,相关的内容如下:

ratio = 1.0
xleft, xright = ax.get_xlim()
ybottom, ytop = ax.get_ylim()
ax.set_aspect(abs((xright-xleft)/(ybottom-ytop))*ratio)

这个链接还对 matplotlib 使用的不同坐标系有一个清晰的解释。

感谢所有收到的精彩回答——尤其是@Yann 的,它仍然是冠军。

使用 plt.gca ()获取当前轴和设置方面的一个简单选项

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

代替你的最后一句台词

就我而言,以下设置最有效:

plt.figure(figsize=(16,9))

其中(16,9)是你的情节长宽比。