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

nee*_*hiv 217 python plot visualization matplotlib

我正在学习matplotlib通过学习示例来学习,并且在创建单个绘图之前,许多示例似乎包括如下所示的行...

fig, ax = plt.subplots()
Run Code Online (Sandbox Code Playgroud)

这里有些例子...

我看到这个函数用了很多,尽管这个例子只是试图创建一个图表.还有其他一些优势吗?官方演示subplots()也用于f, ax = subplots创建单个图表时,它之后只引用了ax.这是他们使用的代码.

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

jon*_*har 273

plt.subplots()是一个返回包含图形和轴对象的元组的函数.因此,在使用时fig, ax = plt.subplots(),将此元组解压缩到变量figax.有fig,如果你想改变人物级别的属性或保存数字作为以后的图像文件是非常有用的(例如用fig.savefig('yourfilename.png').你当然不必使用返回的数字对象,但因此它经常可以看到很多人都用到它.此外,所有轴对象(具有绘图方法的对象)都具有父图形对象,因此:

fig, ax = plt.subplots()
Run Code Online (Sandbox Code Playgroud)

比这更简洁:

fig = plt.figure()
ax = fig.add_subplot(111)
Run Code Online (Sandbox Code Playgroud)

  • 非常好的解释.这是关于它的文档 - http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.subplots (6认同)
  • 为什么我们总是在子图中使用111作为参数? (2认同)
  • @Priyansh 并不总是如此。如果您想要 4 个图表,可以使用“fig.add_subplot(221)”(或分别为 222、223、224)获得“ax11、ax12、ax21、ax22”。 (2认同)

Dus*_*ash 38

这里只是一个补充.

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

正如文档中所提到的,我们可以使用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)
Run Code Online (Sandbox Code Playgroud)

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

那么让我们再试一次:

fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(nrows=2, ncols=2)
Run Code Online (Sandbox Code Playgroud)

并检查类型:

type(fig) #<class 'matplotlib.figure.Figure'>
type(ax1) #<class 'matplotlib.axes._subplots.AxesSubplot'>
Run Code Online (Sandbox Code Playgroud)

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

fig, [ax1, ax2, ax3, ax4] = plt.subplots(nrows=1, ncols=4)
Run Code Online (Sandbox Code Playgroud)

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

希望这对你有所帮助.

  • 如果你有很多子图怎么办?这样做更容易:`fig,axes = plt.subplots(nrows = 10,ncols = 3)`和`axes = axes.flatten()`.现在你可以用它的索引来引用每个子图:`axes [0]`,`axes [1]`,... (5认同)
  • 如果您的子图有标题,请不要忘记添加 plt.tight_layout() (2认同)
  • @BallpointBen刚刚意识到你可以通过执行以下操作来解决这个问题:“fig,axes=plt.subplots(nrows=1,ncols=3,squeeze=False)” (2认同)
  • @BallpointBen 如果使用脚本来运行连续的子图会怎么样?你不需要做一些`if col &gt; row: col -= row; row += 1` 因为如果你把它压平,你只需走过.. (2认同)

小智 8

除了上面的答案之外,您还可以检查使用type(plt.subplots())which 返回元组的对象类型,另一方面,type(plt.subplot())返回matplotlib.axes._subplots.AxesSubplot您无法解包的返回。

  • 欢迎使用堆栈溢出!这实际上是评论,而不是答案。多一点代表,[您将能够发表评论](//stackoverflow.com/privileges/comment)。谢谢! (5认同)

cre*_*ion 8

使用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(...)
Run Code Online (Sandbox Code Playgroud)

那么为什么我们更喜欢斧头呢?

  • 它是可重构的 - 您可以将一些代码放入采用 Axes 对象的函数中,并且不依赖于全局状态
  • 更容易过渡到具有多个子图的情况
  • 一个一致/熟悉的界面,而不是在两个界面之间切换
  • 深入了解 matplotlib 所有功能的唯一方法

全局状态版本以这种方式创建,以便于交互使用,并且成为 Matlab 用户熟悉的界面,但在较大的程序和脚本中,此处概述的要点倾向于使用 Axes 界面。

有一篇 matplotlib 博客文章更深入地探讨了这个主题:Pyplot vs Object Oriented Interface

处理两个世界相对容易。例如,我们总是可以询问当前轴:(ax = plt.gca()“获取当前轴”)。


Lig*_*t_B 7

作为补充的问题和答案,上面也有一个重要区别plt.subplots()plt.subplot(),通知失踪's'底。

可以plt.subplots()一次制作所有子图,然后将子图的图形和轴(复数轴)作为元组返回。可以将图形理解为在其中绘制草图的画布。

# create a subplot with 2 rows and 1 columns
fig, ax = plt.subplots(2,1)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

但是,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)
Run Code Online (Sandbox Code Playgroud)

共享轴 但是,使用时plt.subplot(),必须为每个轴分别指定,这可能会很麻烦。