Matplotlib:固定图形左边缘与y轴之间的间距

7

我使用Python 2.7和Matplotlib制作了两个图表,并将它们保存为*.png文件。保存后,两个图像的分辨率相同 - 宽度为1099像素,高度为619像素。

然而,当我将保存的*.png图像垂直对齐(如下所示),y轴和图像最左侧点之间的间距不相同 - 请参见下面的abenter image description here

我的意思是,图像左侧到y轴的距离不同(a不等于b)。

单击图像进行放大并查看此内容。

问题: 是否有办法强制y轴从与图像左侧的特定位置开始?

注意: 我不关心刻度标签和轴标签之间的空格 - 我可以使用类似ax.yaxis.labelpad(25)的东西来调整这个。但是,我不知道如何修复图像左边和y轴之间的空间。

注意2: 我使用以下方式创建我的图表:

fig = plt.figure(1)
ax = fig.add_subplot(111)
fig.tight_layout()

2
这正是 tight_layout() 应该调整的内容。在 Figure 中,艺术家们被放置/调整为 [0, 1] 的单位空间。在渲染时,该空间被转换为屏幕/像素空间。你所看到的是 tight_layout 的一种特性,而不是 bug。如果您不想要这个特性,请不要使用 tight_layout - tacaswell
相关:更改 轴和其对应标签之间的距离 - ijuneja
2个回答

7

如果我想在matplotlib中对图形边距的大小进行精细控制,我通常会这样设置我的代码。此外,我还展示了如何设置ylabel的位置,这样您可以轻松地将两个图的ylabels对齐。

import matplotlib.pyplot as plt

plt.close('all')

#---- create figure ----

fwidth = 8.  # total width of the figure in inches
fheight = 4. # total height of the figure in inches

fig = plt.figure(figsize=(fwidth, fheight))

#---- define margins -> size in inches / figure dimension ----

left_margin  = 0.95 / fwidth
right_margin = 0.2 / fwidth
bottom_margin = 0.5 / fheight
top_margin = 0.25 / fheight

#---- create axes ----

# dimensions are calculated relative to the figure size

x = left_margin    # horiz. position of bottom-left corner
y = bottom_margin  # vert. position of bottom-left corner
w = 1 - (left_margin + right_margin) # width of axes
h = 1 - (bottom_margin + top_margin) # height of axes

ax = fig.add_axes([x, y, w, h])

#---- Define the Ylabel position ----

# Location are defined in dimension relative to the figure size  

xloc =  0.25 / fwidth 
yloc =  y + h / 2.  

ax.set_ylabel('yLabel', fontsize=16, verticalalignment='top',
              horizontalalignment='center')             
ax.yaxis.set_label_coords(xloc, yloc, transform = fig.transFigure)

plt.show(block=False)
fig.savefig('figure_margins.png')

这将产生一个8in x 4in的图形,左、右、下和上边缘的边距分别为0.95、0.2、0.5和0.25英寸。采用这种方法的好处之一是边距的大小以绝对单位(英寸)定义,这意味着即使改变图形的大小,它们也会保持一致。
至于ylabel,水平方向上,标签的顶部距离图形左侧边缘0.25英寸,而垂直方向上,标签的中心对应于轴的中心。请注意,由于ylabel旋转了90度,因此实际上垂直对齐和水平对齐的含义被倒置了。
下面显示了使用上述代码输出的结果,其中y轴限制分别设置为[0,1]和[0,18]。 enter image description here enter image description here

非常感谢。你的代码 w = 1 - (left_margin + right_margin) 是我之前缺失的基本理解。你能否也展示一下当你设置 ax.set_ylim([0,18.0]) 时的图形以供比较? - edesz
1
@WR 很高兴能帮到你。关于第二个图表的想法很好,我已经添加了它。 - Jean-Sébastien
你能解释一下你倒数第三行的代码吗?这一行是 ax.yaxis.set_label_coords(xloc, yloc, transform=fig.transFigure) - edesz
1
默认情况下,“set_label_coords”接受相对于轴大小的维度中的(x,y)。在您的情况下,如果它是相对于图形大小定义的,则认为这将是更好的设计。这就是为什么我添加了“fig.transFigure”。这使得可以使用与其余代码一致的方法设置标签位置。此外,即使更改图形的大小,位置也应该保持良好。 - Jean-Sébastien
1
在这种情况下,如果您的4个子图具有相同的水平尺寸,我会手动定义y轴位置,相对于坐标轴,就像这里所示:https://dev59.com/sWIk5IYBdhLWcg3wbtub#19277494。不过需要手动调整x位置。使用`get_ticklabel_extents`方法可以实现更自动化的方法。 - Jean-Sébastien
显示剩余3条评论

4

我认为在创建轴(将轴添加到图形对象)时,您可以设置此属性(图形边缘和轴之间的空格)。以下是一些简单示例代码,可生成四周具有宽松间距的两个轴:

import matplotlib.pyplot as plt

f1 = plt.figure()
ax1 = f1.add_axes([0.2, 0.2, 0.6, 0.6]) # List is [left, bottom, width, height]
ax1.axis([0, 1, 0, 1])
plt.savefig('ax1.png')

f2 = plt.figure()
ax2 = f2.add_axes([0.2, 0.2, 0.6, 0.6])
ax2.axis([0, 1000, 0, 1000])
plt.savefig('ax2.png')

你可以在这里找到更多相关信息:
http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.add_axes 编辑: 你可以使用subplots_adjust来实现类似的结果。使用你的示例代码:
fig = plt.figure(1)
ax = fig.add_subplot(111)
fig.tight_layout()
plt.subplots_adjust(left=0.2, bottom=0.2, right=0.8, top=0.8)

我正在使用 fig = plt.figure(1)ax = fig.add_subplot(111) 添加一个子图。有没有办法将 .add_axes() 集成到这个过程中? - edesz
请查看我在原帖中所做的编辑,以了解我如何创建我的图表。让我知道你的想法。 - edesz
@WR дҪ дёәд»Җд№ҲдёҚиғҪжҲ–дёҚжғіз”ЁjwintermжҸҗеҮәзҡ„ax = fig.add_axes([x, y, w, h])жӣҝжҚўax = fig.add_subplot(111)е‘ўпјҹиҝҷдјјд№ҺжҳҜдёҖдёӘеҗҲзҗҶзҡ„и§ЈеҶіж–№жЎҲпјҢеҸҜд»ҘжҺ§еҲ¶иҫ№и·қзҡ„еӨ§е°ҸгҖӮ - Jean-Sébastien
1
你对第一部分的解释是正确的,[0.2, 0.1...] 确实意味着它将从左侧开始20%,从底部开始10%,但是 ...1, 1] 会使轴的宽度和高度占据整个图形的100%,有效地使轴的一部分超出图形边缘。因此,[0.0, 0.0, 1.0, 1.0] 将在图形上创建一个从左下角开始并占据整个图形的轴,而[0.15, 0.15, 0.8, 0.8] 可能更符合默认行为(其中有空间用于轴标签等)。 - jwinterm
@jwinterm:对于subplots_adjust版本,您的设置(0.2,0.8)有效。但是左侧使用较小的值,右侧使用较大的值是否可行?例如0.15、0.85不起作用,但我不明白为什么。这有原因吗? - edesz
显示剩余2条评论

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