Python 具有不同y轴的子地块中的纵横比

Python 具有不同y轴的子地块中的纵横比,python,matplotlib,Python,Matplotlib,我希望下面的代码生成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(22

我希望下面的代码生成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默认生成正确的内容(下图):

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


我不太清楚你想从你的问题中得到什么

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

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

如果您希望它们都共享其轴限制,但要具有
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轴填充的空间与其所在图形的大小成比例。)

将 另一篇我恐怕再也找不到的帖子,我制作了一个代码,精确地设置盒子与给定值的比率

让desired_box_ratio表示长方体y侧和x侧之间的所需比率。 temp_Reverse_axis_ratio是当前绘图的x和y边之间的比率;由于“纵横比”是y和x比例(而不是轴)之间的比率,我们需要将纵横比设置为所需的x轴比例*温度逆比例

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()
理论 在matplotlib中。不同坐标系之间的差异确实会让很多人感到困惑。OP想要的是显示坐标中的纵横比,但是
ax.set\u aspect()
正在数据坐标中设置纵横比。它们之间的关系可以表述为:

aspect = 1.0/dataRatio*dispRatio
其中,
aspect
是在
set\u aspect
方法中使用的参数,
dataRatio
是数据坐标中的纵横比,
dispRatio
是显示坐标中的所需纵横比

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

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()

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

嗨,乔!谢谢你关注我的问题。很抱歉给您带来了混乱。你的两个选项都没有提供我想要的。第一个选项是最接近的。如果每个子地块都有自己的y轴限制,那就太完美了。这就是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\u子地块(221+i-1)平面图(np.arange(0,(i)*4,i))平面图我已经在我的原始问题中添加了这段代码生成的图片Hi Joe,差不多了!这很完美,只是我希望所有Suplot的x轴限制都在0到3之间。我在原始问题中包含的图片是我想要的一切,但轴之间的纵横比不正确。所以现在它有点像1/2,但我看起来很好抱歉,我还是很困惑…如果轴的限制或大小都不改变,纵横比就不可能是常数。你似乎要求的绘图是完全相同的大小,具有相同的纵横比,相同的x轴限制,但不同的y轴限制。根据定义,这是不可能的。我想我只是误解了你的问题在…上,我试着跟随你的教程,这是非常清楚的,但是,当y轴有一个对数刻度时,它不起作用,有没有关于在对数刻度上保持y轴的同时加宽x轴的想法?对不起,我不确定。也许你可以在这篇文章的基础上打开一个关于堆栈溢出的新问题。
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()
aspect = 1.0/dataRatio*dispRatio
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()