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


265

我正在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')

11
好吧,它简短明了,您可以在一个步骤中同时获得图形和轴两个参考。这是pythonic,因为它很漂亮:)
cel

Answers:


322

plt.subplots()是一个返回包含图形和轴对象的元组的函数。因此,在使用时fig, ax = plt.subplots(),将此元组解压缩到变量fig和中axfig如果您要更改图形级属性或以后将图形另存为图像文件(例如,使用fig.savefig('yourfilename.png')),则具有很有用。您当然不必使用返回的图形对象,但是许多人以后会使用它,因此很常见。另外,所有轴对象(具有绘图方法的对象)总有一个父图形对象,因此:

fig, ax = plt.subplots()

比这更简洁:

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

7
很好的解释。下面是它的文档- matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.subplots
bretcj7

2
为什么我们总是在子图中使用111作为参数?
Priyansh

@Priyansh,因为它是从Matlab语法继承的
pcko1

@Priyansh并非总是如此。如果要4张图,可以ax11, ax12, ax21, ax22使用fig.add_subplot(221)(或分别为222、223、224)。
Guimoute

49

这里只是一个补充。

下面的问题是,如果要在图中添加更多子图该怎么办?

如文档中所述,我们可以用来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'>

当然,如果将参数用作(nrows = 1,ncols = 4),则格式应为:

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

因此,只需记住将列表的构造与我们在图中设置的子图网格相同即可。

希望这对您有帮助。


2
如果您的子图有标题,请不要忘记添加plt.tight_layout()
哥达

12
如果您有很多子图怎么办?这样更容易做到:fig, axes = plt.subplots(nrows=10, ncols=3)axes = axes.flatten()。现在,你可以通过它的指数是指每一个插曲:axes[0]axes[1],...
纪尧姆

如果我希望其中一个子图跨越多个列或行,该怎么办?subplots命令可行吗?
高塔

1
@BallpointBen我不确定if是否可以正常工作nrows=1,因为axes返回的长度等于ncols
Ben

1
@BallpointBen刚刚意识到您可以通过以下方法解决此问题:fig, axes = plt.subplots(nrows=1, ncols=3, squeeze=False)
Ben

14

作为补充的问题和答案,上面也有一个重要区别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(),必须为每个轴分别指定,这可能会很麻烦。


1
您的代码行将ax3 = plt.subplot(2,1,3) 不起作用,因为它是2比1(只有2个图形)。
Cloud Cho

1
谢谢,修复它。最后一个代码块中还需要进行其他更改。
Light_B

2

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


4
欢迎使用Stack Overflow!这实际上是评论,而不是答案。有了更多代表,您就可以发表评论。谢谢!
Miroslav Glamuzina '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.