我希望以下代码生成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轴长度比的功能。
答案 0 :(得分:9)
我无法从你的问题中说出你想要的东西。
您是否希望所有图表都具有相同的数据限制?
如果是这样,请使用共享轴(我在这里使用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()
答案 1 :(得分:2)
将Joe Kington的答案与new pythonic style for shared axes square subplots in matplotlib?结合起来 另一篇文章,我恐怕再也找不到了,我制作了一个代码,用于精确设置框的比例为给定值。
让desired_box_ratioN指示框的y和x边之间的所需比率。 temp_inverse_axis_ratioN是当前图的x和y边之间的比率;因为'方面'是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()
答案 2 :(得分:1)
Different coordinate systems exists。不同坐标系之间的差异确实会让很多人感到困惑。 OP想要的是显示坐标中的宽高比,但ax.set_aspect()
是在数据坐标中设置宽高比。他们的关系可以表述为:
aspect = 1.0/dataRatio*dispRatio
其中,aspect
是set_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()
我还写了一篇关于所有这些内容的详细帖子here。