Python matplotlib - 具有固定纵横比的子图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4747051/
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-18 17:19:59  来源:igfitidea点击:

matplotlib - subplots with fixed aspect ratio

pythonmatplotlib

提问by Peter Waltons

I have a problem with plotting multiple subplots. I would like to set the PHYSICAL aspect ratio of the subplots to a fixed value. In my example I have 12 subplots (4 rows and 3 columns) on a landscape A4 figure. There all subplots are nicely placed on the whole figure, and for all subplots the height is nearly equal to the width.

我在绘制多个子图时遇到问题。我想将子图的物理纵横比设置为固定值。在我的示例中,我在横向 A4 图形上有 12 个子图(4 行 3 列)。所有子图都很好地放置在整个图形上,并且对于所有子图,高度几乎等于宽度。

But if I change the layout of my figure to portrait, the subplots are stretched vertically. And this is exactly what should not happen. I would like to have the same height and width of the subplots as on the landscape figure. Is there a possibility that the aspect ratio of the subplots stay the same?

但是,如果我将图形的布局更改为纵向,则子图会垂直拉伸。而这正是不应该发生的。我希望子图的高度和宽度与景观图上的高度和宽度相同。子图的纵横比是否有可能保持不变?

Thanks in advance, Peter

提前致谢,彼得

EDIT: I have found a workaround. But this just works for non-logarithmic axes...

编辑:我找到了一个解决方法。但这仅适用于非对数轴......

aspectratio=1.0
ratio_default=(ax.get_xlim()[1]-ax.get_xlim()[0])/(ax.get_ylim()[1]-ax.get_ylim()[0])
ax.set_aspect(ratio_default*aspectratio)

回答by Joe Kington

Actually, what you're wanting is quite simple... You just need to make sure that adjustableis set to 'box'on your axes, and you have a set aspect ratio for the axes (anything other than 'auto').

实际上,您想要的非常简单……您只需要确保在您的轴上adjustable设置为'box',并且您为轴设置了纵横比(除了'auto')。

You can either do this with the adjustablekwarg when you create the subplots. Alternatively, you can do this after their creation by calling ax.set_adjustable('box'), or by calling ax.set_aspect(aspect, adjustable='box')(where aspect is either 'equal'or a number).

您可以adjustable在创建子图时使用kwarg执行此操作。或者,您可以在创建后通过调用ax.set_adjustable('box')或调用ax.set_aspect(aspect, adjustable='box')(其中方面是'equal'或数字)来执行此操作。

Now, regardless of how the figure is resized, the subplots will maintain the same aspect ratio.

现在,无论图形如何调整大小,子图都将保持相同的纵横比。

For example:

例如:

import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(2,1,1, adjustable='box', aspect=0.3)
ax2 = fig.add_subplot(2,1,2)

ax1.plot(range(10))
ax2.plot(range(10))

plt.show()


Now, compare how the top subplot responds to resizing, vs. how the bottom subplot responds:

现在,比较顶部子图如何响应调整大小,与底部子图如何响应:



The initial plot alt text

最初的情节 替代文字

Resized to a vertical layout: alt text

调整为垂直布局: 替代文字

Resized to a horizontal layout: alt text

调整为水平布局: 替代文字

回答by wil3

Your workaround works for me. After plotting the data, I call the following function:

你的解决方法对我有用。绘制数据后,我调用以下函数:

def fixed_aspect_ratio(ratio):
    '''
    Set a fixed aspect ratio on matplotlib plots 
    regardless of axis units
    '''
    xvals,yvals = gca().axes.get_xlim(),gca().axes.get_ylim()

    xrange = xvals[1]-xvals[0]
    yrange = yvals[1]-yvals[0]
    gca().set_aspect(ratio*(xrange/yrange), adjustable='box')

回答by mjo

In reply to the remark about the solution not working for logarithmic plots in the edit to the original question - you need to adapt as follows:

回复关于解决方案不适用于原始问题编辑中的对数图的评论 - 您需要进行如下调整:

def fixed_aspect_ratio_loglog(ratio):
    '''
    Set a fixed aspect ratio on matplotlib loglog plots 
    regardless of axis units
    '''
    xvals,yvals = gca().axes.get_xlim(),gca().axes.get_ylim()

    xrange = log(xvals[1])-log(xvals[0])
    yrange = log(yvals[1])-log(yvals[0])
    gca().set_aspect(ratio*(xrange/yrange), adjustable='box')

(Adaptation for semilog plots should now be obvious)

(对半对数图的适应现在应该很明显了)