2011-11-01 211 views
74

我试图做一个方形图(使用imshow),即纵横比为1:1,但我不能。这些工作都不是:如何在matplotlib中设置纵横比?

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有关的问题)。

+5

你试过'ax.axis('equal')',偶然吗?正如大家所说,你做了什么应该可以工作,但'ax.axis'可能是尝试解决方法的另一种途径。 –

+0

http://matplotlib.org/examples/pylab_examples/equal_aspect_ratio.html –

回答

53

第三次的魅力。我的猜测是,这是一个错误,并且Zhenya's answer表示它已在最新版本中修复。我有版本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

我可以想象如果你在图中有多个子图,你w应该将y和x子图的数量作为关键字参数(默认为1)提供给例程。然后使用这些数字和hspacewspace关键字,可以使所有子图具有正确的宽高比。

+0

非常感谢 - 终于使用你的功能的作品!谢谢,谢谢你:-) – jtlz2

+0

对于'get_images'是一个空列表的情况(就像'ax.plot([0,1],[0,2])'一样'',你可以使用'get_xlim'和' get_ylim' – Joel

+0

在我看来,如果使用logscale完成这项工作将无法正常工作,我已经添加了一个测试并处理它的答案,随时将其合并到您的答案中,然后删除我的答案。 – Joel

2

你应该尝试与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)) 

这并产生5×(宽x高)的窗口。

+0

感谢你 - 在改变画布纵横比时确实有一些效果:更具体地说,我需要改变画面的纵横比数字本身,它做以下不(格式化..):图= plt.figure(figsize =(plt.figaspect(2.0))) – jtlz2

17

什么是您运行的matplotlib版本?我最近不得不升级到1.1.0,与此同时,add_subplot(111,aspect='equal')适合我。

+0

It's 1.0.1。也许这是一个答案.. – jtlz2

+0

在'matplotlib'版本'2.0.2'中适用于我。''jupyter notebook' version'5.0.0'。谢谢。 – Sathish

1

此答案是根据Yann的回答。它将设置线性或对数图的纵横比。我使用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) 

很明显,你可以使用你想要的,我用scipy,但numpymath应罚款的log任何版本。