繁体   English   中英

在matplotlib中更改子图的长宽比

[英]Changing aspect ratio of subplots in matplotlib

我创建了一系列简单的灰度图像,并将其绘制在网格中(不幸的是,由于我的信誉不高,所以无法上传图像:()。

伪代码是

# Define matplotlib PyPlot object

nrow =  8
ncol = 12

fig, axes = plt.subplots(nrow, ncol, subplot_kw={'xticks': [], 'yticks': []})
fig.subplots_adjust(hspace=0.05, wspace=0.05)

# Sample the fine scale model at random well locations

for ax in axes.flat:

    plot_data = # some Python code here to create 2D grey scale array...

    # ... create sub-plot

    img = ax.imshow(plot_data, interpolation='none')
    img.set_cmap('gray')

# Display the plot

plt.show()        

我想更改纵横比,以使图垂直压缩并水平拉伸。 我尝试使用ax.set_aspect并将'aspect'作为subplot_kw参数传递,但无济于事。 我还关闭了“自动缩放”功能,但随后只能看到少量像素。 欢迎所有建议!

提前致谢!!

@JoeKington-谢谢! 这是一个很好的答复! 仍然想尽一切办法。 也感谢其他张贴者的建议。 因此,原始图如下所示: http : //imgur.com/Wi6v4cs当我设置'aspect ='auto'时,图如下所示: http : //imgur.com/eRBO6MZ这是一个很大的改进。 我现在要做的就是调整子图的大小,以便以例如2:1的纵向长宽比绘制子图,但该图会填满整个子图。 我猜“ colspan”会这样做吗?

简短答案

您可能想致电:

ax.imshow(..., aspect='auto')

默认情况下, imshow会在调用轴时将轴的纵横比设置为1。 这将覆盖您在创建轴时指定的任何方面。

但是,这是matplotlib中常见的混乱原因。 让我备份并详细说明正在发生的事情。


Matplotlib的布局模型


matplotlib中的aspect是指数据坐标中xscale和yscale的比率。 它不直接控制轴的宽高比。

有以下三项控制matplotlib轴的“外部框”的大小和形状:

  1. 图的大小/形状(下图中红色显示)
  2. 图形坐标中轴的指定范围(例如,子图位置,在下图中以绿色显示)
  3. 轴用于容纳固定纵横比( adjustable参数)的机制。

换句话说,轴始终放置在图形坐标中,其形状/大小始终是图形形状/大小的比率。 (注意:某些东西,例如axes_grid会在绘制时更改此值,以解决此限制。)

但是,给定轴的范围(从其子图位置或显式设置的范围)不一定要占用其大小。 根据aspectadjustable参数, 轴将在其给定范围内收缩


要了解所有事物如何相互作用,让我们在许多不同的情况下画一个圆。

没有固定的方面

在基本情况下(没有为轴设置固定的纵横比),轴将填满图形坐标中分配给它的整个空间(由绿色框显示)。

x和y比例尺(由aspect设置)可以自由更改,从而使圆变形:

在此处输入图片说明

当我们调整图形的大小(交互式或在图形创建时)时,轴将“挤压”它:

在此处输入图片说明


固定长宽比, adjustable='box'

但是,如果设置了绘图的宽高比(默认情况下, imshow将强制将宽高比设置为1),则轴将调整轴外部的大小,以将x和y数据比保持在指定的宽高比。

一个关键点在这里明白了,不过,是该aspect的情节是x和y的数据规模方面。 这不是情节的宽度和高度的方面。 因此,如果aspect1 ,则圆圈将始终是圆圈。

例如,假设我们做了类似的事情:

fig, ax = plt.subplots()
# Plot circle, etc, then:
ax.set(xlim=[0, 10], ylim=[0, 20], aspect=1)

默认情况下, adjustable将是"box" 让我们看看发生了什么:

在此处输入图片说明

轴可以占用的最大空间由绿色框显示。 但是,它必须保持相同的x和y比例。 有两种方法可以完成此操作:更改x和y限制或更改“轴”边界框的形状/大小。 因为轴的adjustable参数设置为默认的"box" ,所以轴会在其最大空间内收缩。

当我们调整图的大小时,它会不断缩小,但是通过使轴用尽分配给轴的最大空间(绿色框)来保持x和y比例:

在此处输入图片说明

两个简短的旁注:

  1. 如果您使用共享轴,并且想使用adjustable="box" ,请改用adjustable="box-forced"
  2. 如果要控制轴在“绿色框”内部的位置,请设置轴的anchor 例如,使用ax.set_anchor('NE')使其“固定”在“绿色框”的右上角,因为它会调整其大小以保持纵横比。

固定宽高比, adjustable="datalim"

adjustable的另一个主要选项是"datalim"

在这种情况下,matplotlib将通过更改轴限制之一来将x和y缩放比例保留在数据空间中。 轴将填满分配给它的整个空间。 但是,如果手动设置x或y限制,则它们可能会被覆盖以允许轴既填充分配给它的全部空间,又将x / y比例保持在指定的aspect

在这种情况下,将x限制设置为0-10,将y限制设置为0-20,并且aspect=1, adjustable='datalim' 请注意,不遵守y限制:

在此处输入图片说明

当我们调整图的大小时,宽高比表示相同,但​​是数据限制发生变化(在这种情况下,不遵守x限制)。

在此处输入图片说明


附带一提,生成上述所有数字的代码位于: https : //gist.github.com/joferkington/4fe0d9164b5e4fe1e247


这与imshow有什么关系?


imshow被调用时,它调用ax.set_aspect(1.0)默认情况下。 由于默认情况下imshow adjustable="box" ,任何带有imshow绘图的行为imshow将类似于上面的第imshow张图片。

例如:

在此处输入图片说明

但是,如果指定imshow(..., aspect='auto') ,则图的宽高比将不会被覆盖,并且图像将“压缩”以占用分配给轴的全部空间:

在此处输入图片说明

另一方面,如果您希望像素保持“正方形”(请注意:取决于extent kwarg所指定的像素,它们可能不是正方形的),则可以忽略Aspect aspect='auto'并设置轴改为"datalim"

例如

ax.imshow(data, cmap='gist_earth', interpolation='none')
ax.set(adjustable="datalim")

在此处输入图片说明

轴形状由图形形状控制

最后要记住的是,轴的形状/尺寸定义为图形形状/尺寸的百分比。

因此,如果要保留轴的长宽比并在相邻子图之间具有固定的间距,则需要定义要匹配的图形形状。 plt.figaspect非常方便。 它仅根据指定的长宽比或2D数组生成width, height的元组(它将从数组的形状而不是内容中获取长宽比)。

对于每个子图网格的示例,每个子图具有2x1的恒定纵横比,您可能会考虑以下内容(请注意,此处我使用aspect="auto" ,因为我们希望图像中的像素保持正方形):

import numpy as np
import matplotlib.pyplot as plt

nrows, ncols = 8, 12
dx, dy = 1, 2
figsize = plt.figaspect(float(dy * nrows) / float(dx * ncols))

fig, axes = plt.subplots(nrows, ncols, figsize=figsize)
for ax in axes.flat:
    data = np.random.random((10*dy, 10*dx))
    ax.imshow(data, interpolation='none', cmap='gray')
    ax.set(xticks=[], yticks=[])

pad = 0.05 # Padding around the edge of the figure
xpad, ypad = dx * pad, dy * pad
fig.subplots_adjust(left=xpad, right=1-xpad, top=1-ypad, bottom=ypad)

plt.show()

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM