在matplotlib中创建相等高度和宽度的正方形子图

30

当我运行这段代码时

from pylab import *

figure()
ax1 = subplot(121)
plot([1, 2, 3], [1, 2, 3])
subplot(122, sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

我的两个子图在X轴方向上被“挤压”了。我该如何使这些子图的Y轴高度等于X轴宽度,对于两个子图都是这样呢?

我正在Ubuntu 10.04上使用matplotlib v.0.99.1.2。

更新2010-07-08:让我们看看一些无法解决问题的方法。

在整天的谷歌搜索后,我认为可能与自动缩放有关。所以我尝试调整了一下。

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
subplot(122, sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

Matplotlib 坚持自动缩放。

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
subplot(122, sharex=ax1, sharey=ax1, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

在这个例子中,数据完全消失了。Matplotlib究竟怎么了?就是这样?

好吧,也许如果我们修复它的纵横比呢?

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
axes().set_aspect('equal')
subplot(122, sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

这个问题会导致第一个子图完全消失。太搞笑了!是谁想出来的?

说真的,这应该是一个很难实现的事情吗?

2个回答

26

当您使用sharex和sharey时,设置图形的纵横比例出现问题。

一个解决方法是不使用共享坐标轴。例如,您可以这样做:

from pylab import *

figure()
subplot(121, aspect='equal')
plot([1, 2, 3], [1, 2, 3])
subplot(122, aspect='equal')
plot([1, 2, 3], [1, 2, 3])
show()

然而,一个更好的解决办法是修改"adjustable"关键字参数... 你想要设置为adjustable='box',但是当你使用共享坐标轴时,它必须是adjustable='datalim'(并且将它设置回'box'会导致错误)。

然而,有第三种选项可以处理这种情况: adjustable="box-forced"

例如:

from pylab import *

figure()
ax1 = subplot(121, aspect='equal', adjustable='box-forced')
plot([1, 2, 3], [1, 2, 3])
subplot(122, aspect='equal', adjustable='box-forced', sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
show()

或者更现代的风格(注意:这部分回答在2010年不起作用):

import matplotlib.pyplot as plt

fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
for ax in axes:
    ax.plot([1, 2, 3], [1, 2, 3])
    ax.set(adjustable='box-forced', aspect='equal')

plt.show()
无论哪种方式,您都会得到类似于:

输入图像描述


我使用axis('equal')来获得更类似于MATLAB的语法。当需要像MATLAB中的"axis square"一样aspect为1时,我使用figure(1, figsize=(6, 6))。 - otterb
不幸的是,共享轴已经消失了,必须手动删除刻度标签。这很不幸:(。比较有效的方法是在subplots选项中使用subplot_kw = {'adjustable':'box-forced','aspect':'equal'}。现在唯一的问题是,“共享”轴仍然显示轴标签... - rubenvb
好的...你在哪里找到了adjustable='box-forced'的API描述?我有点疯了... - Atcold
@atcold - http://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.set_adjustable.html(`ax.set(foo=bar)`是调用`ax.set_foo(bar)`的另一种方式)然而,不同选项在`set_aspect`中所做的工作记录在文档中(可能需要一个文档PR...)http://matplotlib.org/devdocs/api/_as_gen/matplotlib.axes.Axes.set_aspect.html - Joe Kington
所以我遇到了这个问题,但答案似乎是错误的,或者说,它们被微调为 OP 的确切情况。如果将要绘制的数据更改为 ax.plot([1, 2, 3], [2, 4, 6]),则图形的纵横比变为2,而不是相等的。我想 matplotlib 保持刻度比例相等,而不是实际的图形纵横比。如何保持图形纵横比相等,即保持框架为正方形? - Ben Farmer
8
“box-forced”无效,而“box”有效。我正在使用2.1.0版本。 - Tobi G.

2

试试这个:

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False, aspect='equal', xlim=[1,3], ylim=[1,3])
plot([1, 2, 3], [1, 2, 3])
##axes().set_aspect('equal')
ax2 = subplot(122, autoscale_on=False, aspect='equal', xlim=[1,3], ylim=[1,3])
plot([1, 2, 3], [1, 2, 3])
draw()
show()

我将axes()这一行注释掉了,因为这会在任意位置创建一个新的axes,而不是预制位置的subplot

调用subplot实际上创建了一个Axes实例,这意味着它可以使用与Axes相同的属性。

希望这可以帮到你 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接