轴 class - 以给定单位显式设置轴的大小 (width/height)

Axes class - set explicitly size (width/height) of axes in given units

我想使用 matplotlib 创建一个图形,我可以在其中明确指定轴的大小,即我想设置轴 bbox 的宽度和高度。

我环顾四周,找不到解决办法。我通常发现的是如何调整完整图形的大小(包括刻度和标签),例如使用 fig, ax = plt.subplots(figsize=(w, h))

这对我来说非常重要,因为我想要轴的 1:1 比例,即纸上的 1 个单位等于现实中的 1 个单位。例如,如果 xrange 为 0 到 10,主刻度 = 1,x 轴为 10cm,则 1 个主刻度 = 1cm。我会把这张图保存为pdf,导入到latex文档中。

This question 提出了类似的话题,但答案没有解决我的问题(使用 plt.gca().set_aspect('equal', adjustable='box') 代码)

从另一个 question 我看到可以获取轴的大小,但不能明确修改它们。

关于如何设置轴框大小而不仅仅是图形大小的任何想法。图形大小应适应轴大小。

谢谢!

对于熟悉 pgfplots in latex, it will like to have something similar to the scale only axis option (see here 的人来说)。

坐标轴大小由图形大小和图形间距决定,可以使用figure.subplots_adjust()设置。相反,这意味着您可以通过考虑图形间距来设置图形大小来设置轴大小:

import matplotlib.pyplot as plt

def set_size(w,h, ax=None):
    """ w, h: width, height in inches """
    if not ax: ax=plt.gca()
    l = ax.figure.subplotpars.left
    r = ax.figure.subplotpars.right
    t = ax.figure.subplotpars.top
    b = ax.figure.subplotpars.bottom
    figw = float(w)/(r-l)
    figh = float(h)/(t-b)
    ax.figure.set_size_inches(figw, figh)

fig, ax=plt.subplots()

ax.plot([1,3,2])

set_size(5,5)

plt.show()

似乎 Matplotlib 有帮助程序 类 允许您定义具有固定大小的轴 Demo fixed size axes

我发现 ImportanceofBeingErnests 的答案修改了图形大小以调整坐标轴大小,结果与我用来制作发布就绪图的特定 matplotlib 设置不一致。最终图形尺寸存在一些小错误,我无法找到解决问题的方法。对于大多数用例,我认为这不是问题,但是在合并多个 pdf 进行发布时,错误很明显。

我没有开发一个最小的工作示例来找出我在图形大小调整方法中遇到的真正问题,而是找到了一个解决方法,它使用利用分隔符的固定轴大小 class。

from mpl_toolkits.axes_grid1 import Divider, Size
def fix_axes_size_incm(axew, axeh):
    axew = axew/2.54
    axeh = axeh/2.54

    #lets use the tight layout function to get a good padding size for our axes labels.
    fig = plt.gcf()
    ax = plt.gca()
    fig.tight_layout()
    #obtain the current ratio values for padding and fix size
    oldw, oldh = fig.get_size_inches()
    l = ax.figure.subplotpars.left
    r = ax.figure.subplotpars.right
    t = ax.figure.subplotpars.top
    b = ax.figure.subplotpars.bottom

    #work out what the new  ratio values for padding are, and the new fig size.
    neww = axew+oldw*(1-r+l)
    newh = axeh+oldh*(1-t+b)
    newr = r*oldw/neww
    newl = l*oldw/neww
    newt = t*oldh/newh
    newb = b*oldh/newh

    #right(top) padding, fixed axes size, left(bottom) pading
    hori = [Size.Scaled(newr), Size.Fixed(axew), Size.Scaled(newl)]
    vert = [Size.Scaled(newt), Size.Fixed(axeh), Size.Scaled(newb)]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), hori, vert, aspect=False)
    # the width and height of the rectangle is ignored.

    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    #we need to resize the figure now, as we have may have made our axes bigger than in.
    fig.set_size_inches(neww,newh)

注意事项:

  • 在轴实例上调用 set_axes_locator() 后,您会破坏 tight_layout() 函数。
  • 您选择的原始图形大小将无关紧要,最终图形大小由您选择的轴大小和 labels/tick labels/outward 刻度的大小决定。
  • 此方法不适用于颜色比例尺。
  • 这是我第一次出现堆栈溢出 post。

另一种使用 fig.add_axes 的方法非常准确。我也包括了 1 厘米的网格

import matplotlib.pyplot as plt
import matplotlib as mpl

# This example fits a4 paper with 5mm margin printers

# figure settings
figure_width = 28.7 # cm
figure_height = 20 # cm
left_right_magrin = 1 # cm
top_bottom_margin = 1 # cm

# Don't change
left   = left_right_magrin / figure_width # Percentage from height
bottom = top_bottom_margin / figure_height # Percentage from height
width  = 1 - left*2
height = 1 - bottom*2
cm2inch = 1/2.54 # inch per cm

# specifying the width and the height of the box in inches
fig = plt.figure(figsize=(figure_width*cm2inch,figure_height*cm2inch))
ax = fig.add_axes((left, bottom, width, height))

# limits settings (important)
plt.xlim(0, figure_width * width)
plt.ylim(0, figure_height * height)

# Ticks settings
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(5))
ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(5))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1))

# Grid settings
ax.grid(color="gray", which="both", linestyle=':', linewidth=0.5)

# your Plot (consider above limits)
ax.plot([1,2,3,5,6,7,8,9,10,12,13,14,15,17])

# save figure ( printing png file had better resolution, pdf was lighter and better on screen)
plt.show()
fig.savefig('A4_grid_cm.png', dpi=1000)
fig.savefig('tA4_grid_cm.pdf')

结果: