I'm trying to make a square plot (using imshow), i.e. aspect ratio of 1:1, but I can't. None of these work:
我正在尝试制作一个方形图(使用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')
It seems like the calls are just being ignored (a problem I often seem to have with matplotlib).
看起来这些调用只是被忽略了(我经常在matplotlib中遇到这个问题)。
4 个解决方案
#1
55
Third times the charm. My guess is that this is a bug and Zhenya's answer suggests it's fixed in the latest version. I have version 0.99.1.1 and I've created the following solution:
第三次的魅力。我的猜测是这是一个bug,而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')
This is 'force.png':
这是'force.png':
Below are my unsuccessful, yet hopefully informative attempts.
以下是我的失败,但希望提供信息的尝试。
Second Answer:
第二个答案:
My 'original answer' below is overkill, as it does something similar to axes.set_aspect()
. I think you want to use axes.set_aspect('auto')
. I don't understand why this is the case, but it produces a square image plot for me, for example this script:
下面我的“原始答案”是矫枉过正,因为它类似于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')
Produces an image plot with 'equal' aspect ratio: and one with 'auto' aspect ratio:
生成具有“相等”宽高比的图像图:以及具有“自动”宽高比的图像:
The code provided below in the 'original answer' provides a starting off point for an explicitly controlled aspect ratio, but it seems to be ignored once an imshow is called.
下面“原始答案”中提供的代码为明确控制的宽高比提供了一个起点,但是一旦调用了imshow,它似乎就会被忽略。
Original Answer:
原答案:
Here's an example of a routine that will adjust the subplot parameters so that you get the desired aspect ratio:
下面是一个例程,它将调整子图参数,以便获得所需的宽高比:
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')
This produces a figure like so:
这会产生如下图:
I can imagine if your having multiple subplots within the figure, you would want to include the number of y and x subplots as keyword parameters (defaulting to 1 each) to the routine provided. Then using those numbers and the hspace
and wspace
keywords, you can make all the subplots have the correct aspect ratio.
我可以想象如果你在图中有多个子图,你可能希望将y和x子图的数量作为关键字参数(默认为1)包含在提供的例程中。然后使用这些数字以及hspace和wspace关键字,可以使所有子图具有正确的宽高比。
#2
18
What is the matplotlib
version you are running? I have recently had to upgrade to 1.1.0
, and with it, add_subplot(111,aspect='equal')
works for me.
你正在运行的matplotlib版本是什么?我最近不得不升级到1.1.0,有了它,add_subplot(111,aspect ='equal')对我有用。
#3
2
you should try with figaspect. It works for me. From the docs:
你应该尝试用figaspect。这个对我有用。来自文档:
Create a figure with specified aspect ratio. If arg is a number, use that aspect ratio. > If arg is an array, figaspect will determine the width and height for a figure that would fit array preserving aspect ratio. The figure width, height in inches are returned. Be sure to create an axes with equal with and height, eg
创建具有指定宽高比的图形。如果arg是数字,请使用该宽高比。 >如果arg是一个数组,figaspect将确定一个适合数组保持纵横比的数字的宽度和高度。返回图形宽度,以英寸为单位的高度。确保创建一个等于和高度的轴,例如
Example usage:
用法示例:
# 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)
Edit: I am not sure of what you are looking for. The above code changes the canvas (the plot size). If you want to change the size of the matplotlib window, of the figure, then use:
编辑:我不确定你在找什么。上面的代码更改了画布(绘图大小)。如果要更改matplotlib窗口的大小,请使用:
In [68]: f = figure(figsize=(5,1))
this does produce a window of 5x1 (wxh).
这确实会产生一个5x1(wxh)的窗口。
#4
1
This answer is based on Yann's answer. It will set the aspect ratio for linear or log-log plots. I've used additional information from https://*.com/a/16290035/2966723 to test if the axes are log-scale.
这个答案是基于Yann的回答。它将为线性或对数 - 对数图设置纵横比。我使用了https://*.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)
Obviously you can use any version of log
you want, I've used scipy
, but numpy
or math
should be fine.
显然你可以使用你想要的任何版本的日志,我使用scipy,但是numpy或数学应该没问题。
#1
55
Third times the charm. My guess is that this is a bug and Zhenya's answer suggests it's fixed in the latest version. I have version 0.99.1.1 and I've created the following solution:
第三次的魅力。我的猜测是这是一个bug,而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')
This is 'force.png':
这是'force.png':
Below are my unsuccessful, yet hopefully informative attempts.
以下是我的失败,但希望提供信息的尝试。
Second Answer:
第二个答案:
My 'original answer' below is overkill, as it does something similar to axes.set_aspect()
. I think you want to use axes.set_aspect('auto')
. I don't understand why this is the case, but it produces a square image plot for me, for example this script:
下面我的“原始答案”是矫枉过正,因为它类似于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')
Produces an image plot with 'equal' aspect ratio: and one with 'auto' aspect ratio:
生成具有“相等”宽高比的图像图:以及具有“自动”宽高比的图像:
The code provided below in the 'original answer' provides a starting off point for an explicitly controlled aspect ratio, but it seems to be ignored once an imshow is called.
下面“原始答案”中提供的代码为明确控制的宽高比提供了一个起点,但是一旦调用了imshow,它似乎就会被忽略。
Original Answer:
原答案:
Here's an example of a routine that will adjust the subplot parameters so that you get the desired aspect ratio:
下面是一个例程,它将调整子图参数,以便获得所需的宽高比:
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')
This produces a figure like so:
这会产生如下图:
I can imagine if your having multiple subplots within the figure, you would want to include the number of y and x subplots as keyword parameters (defaulting to 1 each) to the routine provided. Then using those numbers and the hspace
and wspace
keywords, you can make all the subplots have the correct aspect ratio.
我可以想象如果你在图中有多个子图,你可能希望将y和x子图的数量作为关键字参数(默认为1)包含在提供的例程中。然后使用这些数字以及hspace和wspace关键字,可以使所有子图具有正确的宽高比。
#2
18
What is the matplotlib
version you are running? I have recently had to upgrade to 1.1.0
, and with it, add_subplot(111,aspect='equal')
works for me.
你正在运行的matplotlib版本是什么?我最近不得不升级到1.1.0,有了它,add_subplot(111,aspect ='equal')对我有用。
#3
2
you should try with figaspect. It works for me. From the docs:
你应该尝试用figaspect。这个对我有用。来自文档:
Create a figure with specified aspect ratio. If arg is a number, use that aspect ratio. > If arg is an array, figaspect will determine the width and height for a figure that would fit array preserving aspect ratio. The figure width, height in inches are returned. Be sure to create an axes with equal with and height, eg
创建具有指定宽高比的图形。如果arg是数字,请使用该宽高比。 >如果arg是一个数组,figaspect将确定一个适合数组保持纵横比的数字的宽度和高度。返回图形宽度,以英寸为单位的高度。确保创建一个等于和高度的轴,例如
Example usage:
用法示例:
# 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)
Edit: I am not sure of what you are looking for. The above code changes the canvas (the plot size). If you want to change the size of the matplotlib window, of the figure, then use:
编辑:我不确定你在找什么。上面的代码更改了画布(绘图大小)。如果要更改matplotlib窗口的大小,请使用:
In [68]: f = figure(figsize=(5,1))
this does produce a window of 5x1 (wxh).
这确实会产生一个5x1(wxh)的窗口。
#4
1
This answer is based on Yann's answer. It will set the aspect ratio for linear or log-log plots. I've used additional information from https://*.com/a/16290035/2966723 to test if the axes are log-scale.
这个答案是基于Yann的回答。它将为线性或对数 - 对数图设置纵横比。我使用了https://*.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)
Obviously you can use any version of log
you want, I've used scipy
, but numpy
or math
should be fine.
显然你可以使用你想要的任何版本的日志,我使用scipy,但是numpy或数学应该没问题。