更改matplotlib中子图的纵横比

时间:2015-09-17 14:47:19

标签: python 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参数传递,但无济于事。我也关闭了'autoscale',但我只能看到一些像素。欢迎所有建议!

提前致谢!!

@JoeKington - 谢谢!那是一个很棒的回复!!仍然试图让我全神贯注。还要感谢其他海报的建议。所以,原始情节看起来像这样:http://imgur.com/Wi6v4cs 当我设置'aspect ='auto''时,情节如下所示:http://imgur.com/eRBO6MZ 这是一个很大的进步。我现在需要做的就是调整子图大小,以便以2:1的纵向纵横比绘制子图,但是图中填充整个子图。我想'colspan'会这样做吗?

1 个答案:

答案 0 :(得分:47)

简答

您可能想要致电:

ax.imshow(..., aspect='auto')
默认情况下,

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

然而,这是matplotlib中常见的混淆源。让我备份并详细解释一下。

Matplotlib的布局模型

matplotlib中的

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

有三件事可以控制"外框"的尺寸和形状。 matplotlib轴:

  1. 图的大小/形状(下图中以红色显示
  2. 图坐标中指定的Axes范围(例如,下图中的子图位置,以绿色显示
  3. Axes用于适应固定宽高比(adjustable参数)的机制。
  4. 轴始终位于图形坐标中,换句话说,它们的形状/大小始终是图形的形状/大小的比率。 (注意:axes_grid之类的某些内容会在绘制时改变这一点以克服此限制。)

    但是,给定轴的范围(从其子图位置或明确设置的范围)并不一定是它将占用的大小。根据{{​​1}}和aspect参数,轴将在其给定范围内缩小

    为了理解所有事物的相互作用,让我们在很多不同的情况下绘制一个圆圈。

    无固定方面

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

    x和y刻度(由adjustable设置)可以自由更改,扭曲圆圈:

    enter image description here

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

    enter image description here

    固定宽高比,aspect

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

    这里要理解的一个关键点是,图的imshow是x和y数据比例的一个方面。它不是图的宽度和高度的方面。因此,如果aspectaspect,则圆圈将始终为圆圈。

    举个例子,我们说我们做过类似的事情:

    1

    默认情况下,fig, ax = plt.subplots() # Plot circle, etc, then: ax.set(xlim=[0, 10], ylim=[0, 20], aspect=1) adjustable。让我们看看会发生什么:

    enter image description here

    轴可以占用的最大空间由绿色框显示。但是,它必须保持相同的x和y标度。有两种方法可以实现:更改x和y限制或更改Axes边界框的形状/大小。由于Axes的"box"参数设置为默认adjustable,因此Axes在其最大空间内缩小。

    当我们调整图形的大小时,它将继续缩小,但是通过使轴用于减少分配给轴的最大空间(绿色框)来维持x和y比例:

    enter image description here

    两个快速的旁注:

    1. 如果您正在使用共享轴,并希望拥有"box",请改用adjustable="box"
    2. 如果您想控制轴位于"绿色框内的位置"设置轴的adjustable="box-forced"。例如。 anchor让它保持"固定"在"绿色框的右上角"因为它调整了它的大小以保持纵横比。
    3. 固定方面,ax.set_anchor('NE')

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

      在这种情况下,matplotlib将通过更改其中一个轴限制来保持数据空间中的x和y比例。 Axes将填满分配给它的整个空间。但是,如果手动设置x或y限制,则可以覆盖它们以允许轴填充分配给它的完整空间并将x / y比例保持为指定的"datalim"

      在这种情况下,x限制设置为0-10,y限制设置为0-20,aspect。请注意,y限制未被遵守:

      enter image description here

      当我们调整图形时,纵横比也相同,但数据限制发生变化(在这种情况下,x限制不受尊重)。

      enter image description here

      在旁注中,生成上述所有数字的代码位于:https://gist.github.com/joferkington/4fe0d9164b5e4fe1e247

      这与aspect=1, adjustable='datalim'有什么关系?

      调用imshow时,默认情况下会调用imshow。由于默认情况下为ax.set_aspect(1.0),因此任何带有adjustable="box"的情节都会像上面的第3 /第4张图片一样。

      例如:

      enter image description here

      但是,如果我们指定imshow,则图表的宽高比不会被覆盖,图像将会#34;压缩"占用分配给Axes的全部空间:

      enter image description here

      另一方面,如果你想让像素保持" square" (注意:取决于imshow(..., aspect='auto') kwarg指定的内容,它们可能不是正方形),您可以忽略extent并将轴的可调参数设置为aspect='auto'代替。

      E.g。

      "datalim"

      enter image description here

      轴形状由图形

      控制

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

      因此,如果要保留轴的纵横比并在相邻子图之间保留固定的间距,则需要定义要匹配的图形的形状。 ax.imshow(data, cmap='gist_earth', interpolation='none') ax.set(adjustable="datalim") 非常方便。它只是根据指定的宽高比或2D数组生成plt.figaspect的元组(它将采用数组形状的宽高比,而不是内容)。

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

      aspect="auto"

      enter image description here