9

我希望下面的代码生成 4 个相同大小的子图,在我设置的 x 轴和 y 轴的大小之间具有共同的纵横比。参考下面的示例,我希望所有子图看起来都与第一个(左上角)完全相同。现在的问题是 y 轴的大小与其最大值相关。这是我要避免的行为。

import matplotlib.pyplot as plt
import numpy as np

def main(): 

    fig = plt.figure(1, [5.5, 3])
    for i in range(1,5):
        fig.add_subplot(221+i-1, adjustable='box', aspect=1) 
        plt.plot(np.arange(0,(i)*4,i))

    plt.show()

if __name__ == "__main__": 
    main()

令人惊讶的是,matplotlib 默认生成正确的东西(下图):

   import  matplotlib.pyplot as plt 
   import numpy as np 

   def main(): 
       fig = plt.figure(1, [5.5, 3]) 
       for i in range(1,5): 
           fig.add_subplot(221+i-1) 
            plt.plot(np.arange(0,(i)*4,i)) 
       plt.show() 

我只想添加一个控制 x 轴和 y 轴长度之间纵横比的能力。

这是我正在寻找的:

4

3 回答 3

10

我不能完全说出你想要从你的问题中得到什么。

您是否希望所有图都具有相同的数据限制?

如果是这样,请使用共享轴(我在subplots这里使用,但如果您想坚持使用 matlab 样式的代码,可以避免使用它):

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(nrows=2, ncols=2, sharey=True, sharex=True)
for i, ax in enumerate(axes.flat, start=1):
    ax.set(aspect=1)
    ax.plot(np.arange(0, i * 4, i))

plt.show()

在此处输入图像描述

如果您希望他们都共享他们的坐标轴限制,但有adjustable='box'(即非方形坐标轴边界),请使用adjustable='box-forced'

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(nrows=2, ncols=2, sharey=True, sharex=True)
for i, ax in enumerate(axes.flat, start=1):
    ax.set(aspect=1, adjustable='box-forced', xticks=range(i))
    ax.plot(np.arange(0, i * 4, i))

plt.show()

在此处输入图像描述


编辑:对不起,我还是有点困惑。你想要这样的东西吗?

import matplotlib.pyplot as plt 
import numpy as np 

fig, axes = plt.subplots(nrows=2, ncols=2)
for i, ax in enumerate(axes.flat, start=1):
    ax.set(adjustable='datalim', aspect=1)
    ax.plot(np.arange(0, i * 4, i))

plt.show()

在此处输入图像描述


好的,我想我终于明白你的问题了。我们都用“纵横比”表示完全不同的东西。

在 matplotlib 中,绘图的纵横比是指数据限制的相对比例。换言之,如果绘图的纵横比为 1,则斜率为 1 的线将出现在 45 度角。您假设纵横比应用于轴的轮廓,而不是绘制在轴上的数据。

您只希望子图的轮廓是方形的。(在这种情况下,它们都有不同的纵横比,由 matplotlib 定义。)

在这种情况下,您需要一个正方形图形。(还有其他方法,但只是制作一个正方形图形要简单得多。Matplotlib 轴填充的空间与它们所在的图形大小成正比。)

import matplotlib.pyplot as plt 
import numpy as np 

# The key here is the figsize (it needs to be square). The position and size of
# axes in matplotlib are defined relative to the size of the figure.
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8,8))

for i, ax in enumerate(axes.flat, start=1):
    ax.plot(np.arange(0, i * 4, i))

# By default, subplots leave a bit of room for tick labels on the left.
# We'll remove it so that the axes are perfectly square.
fig.subplots_adjust(left=0.1)

plt.show()

在此处输入图像描述

于 2013-02-16T15:34:07.423 回答
2

将Joe Kington的答案与matplotlib 中共享轴方形子图的新 pythonic 风格相结合? 还有一篇恐怕我再也找不到它的帖子了,我编写了一个代码,用于精确设置框与给定值的比率。

让desired_box_ratioN 表示框的y 和x 边之间的期望比率。temp_inverse_axis_ratioN 是当前绘图的 x 和 y 边之间的比率;因为'aspect'是y和x比例(而不是轴)之间的比率,我们需要将aspect设置为desired_box_ratioN * temp_inverse_axis_ratioN。

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(nrows=2, ncols=2)

desired_box_ratioN = 1
for i, ax in enumerate(axes.flat, start=1):
    ax.plot(np.arange(0, i * 4, i))
    temp_inverse_axis_ratioN = abs( (ax.get_xlim()[1] - ax.get_xlim()[0])/(ax.get_ylim()[1] - ax.get_ylim()[0]) )
    ax.set(aspect = desired_box_ratioN * temp_inverse_axis_ratioN, adjustable='box-forced')

plt.show()
于 2014-08-04T14:47:24.810 回答
1

理论

matplotlib中存在不同的坐标系。不同坐标系之间的差异确实可以让很多人感到困惑。OP想要的是显示坐标ax.set_aspect()中的纵横比,但在数据坐标中设置纵横比。他们的关系可以表述为:

aspect = 1.0/dataRatio*dispRatio

其中,aspectset_aspect方法中使用的参数,dataRatio是数据坐标dispRatio的纵横比,是显示坐标中所需的纵横比

实践

有一种get_data_ratio方法可以让我们的代码更简洁。工作代码片段如下所示:

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(nrows=2, ncols=2)

dispRatio = 0.5
for i, ax in enumerate(axes.flat, start=1):
    ax.plot(np.arange(0, i * 4, i))
    ax.set(aspect=1.0/ax.get_data_ratio()*dispRatio, adjustable='box-forced')

plt.show()

我还在这里写了一篇关于所有这些东西的详细帖子。

于 2018-01-08T02:02:47.833 回答