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

Posted

技术标签:

【中文标题】为啥很多例子在 Matplotlib/pyplot/python 中使用 `fig, ax = plt.subplots()`【英文标题】:Why do many examples use `fig, ax = plt.subplots()` in Matplotlib/pyplot/python为什么很多例子在 Matplotlib/pyplot/python 中使用 `fig, ax = plt.subplots()` 【发布时间】:2016-03-13 18:14:27 【问题描述】:

我正在通过学​​习示例来学习使用matplotlib,很多示例似乎在创建单个图之前都包含如下一行...

fig, ax = plt.subplots()

这里有一些例子......

Modify tick label text http://matplotlib.org/examples/pylab_examples/boxplot_demo2.html

我看到这个函数被大量使用,即使这个例子只是试图创建一个图表。有没有其他优势? subplots() 的官方演示在创建单个图表时也使用了f, ax = subplots,之后它只引用了 ax。这是他们使用的代码。

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

【问题讨论】:

嗯,它很短,简洁,您可以在一个步骤中获得两个图形和轴的参考。这是pythonic,因为它很漂亮:) 【参考方案1】:

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

fig, ax = plt.subplots()

比这更简洁:

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

【讨论】:

很好的解释。这是上面的文档 - matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.subplots 为什么我们在子图中总是使用111作为参数? @Priyansh 因为它继承自 Matlab 语法 @Priyansh 并非总是如此。如果您想要 4 个图表,您可以使用 fig.add_subplot(221)(或分别为 222、223、224)获得 ax11, ax12, ax21, ax22 那么附加问题:这样做是否正确:fig = plt.figure(figsize=[20,15]) 然后axes = fig.subplots(2,2, sharex=False, sharey=False)【参考方案2】:

这里只是补充。

下面的问题是,如果我想要图中更多的子图怎么办?

正如文档中提到的,我们可以使用fig = plt.subplots(nrows=2, ncols=2)在一个图形对象中设置一组带有grid(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'>

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

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

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

希望这对你有帮助。

【讨论】:

如果您的子图有标题,请不要忘记添加 plt.tight_layout() 如果你有很多子情节怎么办?这样做更容易:fig, axes = plt.subplots(nrows=10, ncols=3)axes = axes.flatten()。现在您可以通过索引引用每个子图:axes[0], axes[1], ... @BallpointBen 我不确定如果nrows=1 是否有效,那么axes 的返回长度等于ncols @BallpointBen 刚刚意识到您可以通过以下方式解决此问题:fig, axes = plt.subplots(nrows=1, ncols=3, squeeze=False) @BallpointBen 如果您使用脚本运行连续的子图会怎样?你不需要做一些if col &gt; row: col -= row; row += 1,因为如果你把它弄平,你只需穿过..【参考方案3】:

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

可以使用plt.subplots() 一次制作所有子图,并将子图的图形和轴(轴的复数)作为元组返回。可以将图形理解为画布的画布。

# 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(),则必须为每个轴单独指定,这可能会变得很麻烦。

【讨论】:

【参考方案4】:

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

【讨论】:

欢迎来到 Stack Overflow!这实际上是评论,而不是答案。多一点代表,you will be able to post comments。谢谢!【参考方案5】:

使用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 Object Oriented Interface

处理两个世界相对容易。例如,我们可以始终请求当前坐标区:ax = plt.gca() ("get current axes")。

【讨论】:

很长一段时间以来我一直想知道为什么界面如此混乱(例如plt.xlabel vs ax.set_xlabel)但现在它是有道理的 - 这是两个独立的界面!

以上是关于为啥很多例子在 Matplotlib/pyplot/python 中使用 `fig, ax = plt.subplots()`的主要内容,如果未能解决你的问题,请参考以下文章

九个例子玩转Matplotlib.pyplot 三维绘图

为啥我的 pyplot.plot 数字没有正确保存?

Matplotlib/pyplot:如何强制执行轴范围?

matplotlib.pyplot的使用

python中matplotlib.pyplot的使用示例

python matplotlib.pyplot学习记录