为什么很多例子在Matplotlib/pyplot/python中使用' fig, ax = plt.subplots() '

我正在学习使用matplotlib通过研究例子,和许多例子似乎包括如下一行在创建一个单一的情节之前…

fig, ax = plt.subplots()

下面是一些例子。

我看到这个函数被使用了很多次,即使这个例子只是试图创建一个图表。还有其他好处吗?subplots()的官方演示在创建单个图表时也使用f, ax = subplots,并且在此之后只引用ax。这是他们使用的代码。

# Just a figure and one subplot
f, ax = plt.subplots()
ax.plot(x, y)
ax.set_title('Simple plot')
416874 次浏览

plt.subplots()是一个函数,返回一个包含图形和轴对象的元组。因此,当使用fig, ax = plt.subplots()时,你将这个元组解包到变量figax中。如果你想更改图形级别的属性或稍后将图形保存为图像文件(例如使用fig.savefig('yourfilename.png')),使用fig是非常有用的。你当然不需要使用返回的图形对象,但很多人后来会使用它,所以它很常见。同样,所有坐标轴对象(具有绘图方法的对象)都有一个父图形对象,因此:

fig, ax = plt.subplots()

比这个更简洁:

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

这只是一个补充。

下面的问题是,如果我想在图中有更多的子图呢?

正如在文档中提到的,我们可以使用fig = plt.subplots(nrows=2, ncols=2)在一个图形对象中设置一组网格(2,2)的子图。

然后,正如我们所知,fig, ax = plt.subplots()返回一个元组,让我们先尝试fig, ax1, ax2, ax3, ax4 = plt.subplots(nrows=2, ncols=2)

ValueError: not enough values to unpack (expected 4, got 2)

它会引发一个错误,但不用担心,因为我们现在看到plt.subplots()实际上返回了一个包含两个元素的元组。第一个必须是一个图形对象,另一个应该是一组子图对象。

让我们再试一次:

fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(nrows=2, ncols=2)

检查类型:

type(fig) #<class 'matplotlib.figure.Figure'>
type(ax1) #<class 'matplotlib.axes._subplots.AxesSubplot'>

当然,如果你使用参数为(nrows=1, ncols=4),那么格式应该是:

fig, [ax1, ax2, ax3, ax4] = plt.subplots(nrows=1, ncols=4)

所以请记住,保持列表的结构与我们在图中设置的子图网格相同。

希望这对你有帮助。

作为问题和以上答案的补充,plt.subplots()plt.subplot()之间还有一个重要的区别,注意结尾缺少's'

可以使用plt.subplots()一次性创建它们的所有子图,它将子图的图形和轴(axis的复数)作为元组返回。人物可以理解为画布,你可以在上面画草图。

# create a subplot with 2 rows and 1 columns
fig, ax = plt.subplots(2,1)

然而,如果你想分别添加子图,你可以使用plt.subplot()。它只返回一个子图的轴。

fig = plt.figure() # create the canvas for plotting
ax1 = plt.subplot(2,1,1)
# (2,1,1) indicates total number of rows, columns, and figure number respectively
ax2 = plt.subplot(2,1,2)

然而,plt.subplots()是首选,因为它让你更容易选择直接自定义整个图形

# for example, sharing x-axis, y-axis for all subplots can be specified at once
fig, ax = plt.subplots(2,2, sharex=True, sharey=True)

共享轴 而使用plt.subplot(),则必须为每个轴单独指定,这可能会变得很麻烦

除了上面的答案,你可以使用type(plt.subplots())检查对象的类型,它返回一个元组,另一方面,type(plt.subplot())返回matplotlib.axes._subplots.AxesSubplot,你不能解包。

使用plt.subplots()很流行,因为它给你一个Axes对象,并允许你使用Axes接口来定义图形。

另一种方法是使用全局状态接口,plt.plot等功能:

import matplotlib.pyplot as plt


# global state version - modifies "current" figure
plt.plot(...)
plt.xlabel(...)


# axes version - modifies explicit axes
ax.plot(...)
ax.set_xlabel(...)

所以为什么我们更喜欢Axes吗?

  • 它是可重构的——您可以将部分代码放入一个接受Axes对象的函数中,并且不依赖于全局状态
  • 更容易过渡到有多个子情节的情况
  • 一个一致/熟悉的界面,而不是在两个界面之间切换
  • 访问matplotlib所有特性深度的唯一方法

创建全局状态版本是为了便于交互使用,并成为Matlab用户熟悉的接口,但在较大的程序和脚本中,这里概述的要点有利于使用Axes接口。

有一篇matplotlib博客文章更深入地探讨了这个主题:Pyplot vs面向对象接口

同时处理这两个问题相对容易。例如,我们可以总是请求当前轴:ax = plt.gca()(“get current axes")”。

fig.tight_layout ()

这样的特性非常方便,如果xticks_labels离开了plot-window,这样的行可以帮助适应xticks_labels &如果图表在plt窗口中的自动定位工作不正确,则整个图表将转到窗口。只有在plt窗口中使用fig-object时,此代码行才有效

fig, ax = plt.subplots(figsize=(10,8))


myData.plot(ax=ax)
plt.xticks(fontsize=10, rotation=45)


fig.tight_layout()
plt.show()