如何使用 pyplot 使一个轴占据多个子图

发布于 2024-08-22 03:16:27 字数 519 浏览 10 评论 0原文

我想在一个图中包含三个图。该图应具有二乘二的子图布局,其中第一个图应占据前两个子图单元格(即整个第一行图单元格),其他图应位于单元格 3 和 4 中第一个图的下方。

我知道 MATLAB 通过使用 subplot 命令来实现这一点,如下所示:

subplot(2,2,[1,2]) % the plot will span subplots 1 and 2

Is it also possible in pyplot to have a single axis attend more subplot? pyplot.subplot 的文档字符串没有谈论它。

有人有一个简单的解决方案吗?

I would like to have three plots in a single figure. The figure should have a subplot layout of two by two, where the first plot should occupy the first two subplot cells (i.e. the whole first row of plot cells) and the other plots should be positioned underneath the first one in cells 3 and 4.

I know that MATLAB allows this by using the subplot command like so:

subplot(2,2,[1,2]) % the plot will span subplots 1 and 2

Is it also possible in pyplot to have a single axes occupy more than one subplot?
The docstring of pyplot.subplot doesn't talk about it.

Anyone got an easy solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

好倦 2024-08-29 03:16:27

您可以简单地这样做:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 7, 0.01)
    
plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x))
    
plt.subplot(2, 2, 3)
plt.plot(x, np.cos(x))
    
plt.subplot(2, 2, 4)
plt.plot(x, np.sin(x)*np.cos(x))

即,第一个图实际上是上半部分的图(该图仅分为 2x1 = 2 个单元格),下面的两个较小的图是在 2x2=4 个单元格网格中完成的。
subplot() 的第三个参数是绘图在网格内的位置(以英语阅读的方向,单元格 1 位于左上角):
例如,在第二个子图 (subplot(2, 2, 3)) 中,轴将转到 2x2 矩阵的第三部分,即左下角。

输入图像描述这里

You can simply do:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 7, 0.01)
    
plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x))
    
plt.subplot(2, 2, 3)
plt.plot(x, np.cos(x))
    
plt.subplot(2, 2, 4)
plt.plot(x, np.sin(x)*np.cos(x))

i.e., the first plot is really a plot in the upper half (the figure is only divided into 2x1 = 2 cells), and the following two smaller plots are done in a 2x2=4 cell grid.
The third argument to subplot() is the position of the plot inside the grid (in the direction of reading in English, with cell 1 being in the top-left corner):
for example in the second subplot (subplot(2, 2, 3)), the axes will go to the third section of the 2x2 matrix i.e, to the bottom-left corner.

enter image description here

雨轻弹 2024-08-29 03:16:27

使用 Gridspec 制作多列/行子图布局展示了一种执行此操作的方法GridSpec。该示例的简化版本包含 3 个子图,如下所示

import matplotlib.pyplot as plt

fig = plt.figure()

gs = fig.add_gridspec(2,2)
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[1, :])

plt.show()

在此处输入图像描述

The Using Gridspec to make multi-column/row subplot layouts shows a way to do this with GridSpec. A simplified version of the example with 3 subplots would look like

import matplotlib.pyplot as plt

fig = plt.figure()

gs = fig.add_gridspec(2,2)
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[1, :])

plt.show()

enter image description here

远昼 2024-08-29 03:16:27

要让多个子图占据一个轴,您可以简单地执行以下操作:

from matplotlib import pyplot as plt
import numpy as np

b=np.linspace(-np.pi, np.pi, 100)

a1=np.sin(b)

a2=np.cos(b)

a3=a1*a2

plt.subplot(221)
plt.plot(b, a1)
plt.title('sin(x)')

plt.subplot(222)
plt.plot(b, a2)
plt.title('cos(x)')

plt.subplot(212)
plt.plot(b, a3)
plt.title('sin(x)*cos(x)')

plt.show()

在此处输入图像描述

另一种方法是

plt.subplot(222)
plt.plot(b, a1)
plt.title('sin(x)')

plt.subplot(224)
plt.plot(b, a2)
plt.title('cos(x)')

plt.subplot(121)
plt.plot(b, a3)
plt.title('sin(x)*cos(x)')

plt.show()

在此处输入图像描述

To have multiple subplots with an axis occupy, you can simply do:

from matplotlib import pyplot as plt
import numpy as np

b=np.linspace(-np.pi, np.pi, 100)

a1=np.sin(b)

a2=np.cos(b)

a3=a1*a2

plt.subplot(221)
plt.plot(b, a1)
plt.title('sin(x)')

plt.subplot(222)
plt.plot(b, a2)
plt.title('cos(x)')

plt.subplot(212)
plt.plot(b, a3)
plt.title('sin(x)*cos(x)')

plt.show()

enter image description here

Another way is

plt.subplot(222)
plt.plot(b, a1)
plt.title('sin(x)')

plt.subplot(224)
plt.plot(b, a2)
plt.title('cos(x)')

plt.subplot(121)
plt.plot(b, a3)
plt.title('sin(x)*cos(x)')

plt.show()

enter image description here

故事灯 2024-08-29 03:16:27

更现代的答案是:最简单的可能是使用 subplots_mosaic:
https://matplotlib.org/stable/tutorials/provisional/mosaic.html

import matplotlib.pyplot as plt
import numpy as np

# Some example data to display
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig, axd = plt.subplot_mosaic([['left', 'right'],['bottom', 'bottom']],
                              constrained_layout=True)
axd['left'].plot(x, y, 'C0')
axd['right'].plot(x, y, 'C1')
axd['bottom'].plot(x, y, 'C2')
plt.show()

示例 w/ subplot_mosaic

A more modern answer would be: Simplest is probably to use subplots_mosaic:
https://matplotlib.org/stable/tutorials/provisional/mosaic.html

import matplotlib.pyplot as plt
import numpy as np

# Some example data to display
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig, axd = plt.subplot_mosaic([['left', 'right'],['bottom', 'bottom']],
                              constrained_layout=True)
axd['left'].plot(x, y, 'C0')
axd['right'].plot(x, y, 'C1')
axd['bottom'].plot(x, y, 'C2')
plt.show()

Example w/ subplot_mosaic

长不大的小祸害 2024-08-29 03:16:27

对于更细粒度的控制,您可能需要使用 matplotlib.pyplotsubplot2grid 模块。

https://matplotlib.org/stable/api/gridspec_api.html

的一个示例GridSpec 实际应用: 使用 Gridspec 制作多列/行子图布局

import matplotlib.pyplot as plt

from matplotlib.gridspec import GridSpec


def format_axes(fig):
    for i, ax in enumerate(fig.axes):
        ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center")
        ax.tick_params(labelbottom=False, labelleft=False)

fig = plt.figure(layout="constrained")

gs = GridSpec(3, 3, figure=fig)
ax1 = fig.add_subplot(gs[0, :])
# identical to ax1 = plt.subplot(gs.new_subplotspec((0, 0), colspan=3))
ax2 = fig.add_subplot(gs[1, :-1])
ax3 = fig.add_subplot(gs[1:, -1])
ax4 = fig.add_subplot(gs[-1, 0])
ax5 = fig.add_subplot(gs[-1, -2])

fig.suptitle("GridSpec")
format_axes(fig)

plt.show()

使用 Gridspec 制作多列/行子图布局

For finer-grained control you might want to use the subplot2grid module of matplotlib.pyplot.

https://matplotlib.org/stable/api/gridspec_api.html

One example of GridSpec in action: Using Gridspec to make multi-column/row subplot layouts

import matplotlib.pyplot as plt

from matplotlib.gridspec import GridSpec


def format_axes(fig):
    for i, ax in enumerate(fig.axes):
        ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center")
        ax.tick_params(labelbottom=False, labelleft=False)

fig = plt.figure(layout="constrained")

gs = GridSpec(3, 3, figure=fig)
ax1 = fig.add_subplot(gs[0, :])
# identical to ax1 = plt.subplot(gs.new_subplotspec((0, 0), colspan=3))
ax2 = fig.add_subplot(gs[1, :-1])
ax3 = fig.add_subplot(gs[1:, -1])
ax4 = fig.add_subplot(gs[-1, 0])
ax5 = fig.add_subplot(gs[-1, -2])

fig.suptitle("GridSpec")
format_axes(fig)

plt.show()

Using Gridspec to make multi-column/row subplot layouts

浅笑依然 2024-08-29 03:16:27

matplotlib 中有三个主要选项可用于在图中绘制单独的图:

  1. subplot:访问轴数组并添加子图
  2. gridspec:控制底层图形的几何属性(演示)
  3. 子图:将前两个包装在一个方便的 api 中(demo)

到目前为止的帖子已经解决了前两个选项,但没有提到第三个,这是更现代的方法并且基于前两个选项。请参阅具体文档 使用子图和 GridSpec 组合两个子图


更新

临时的 subplot_mosaic 可能是一个更好的改进@Jody Klymak 的帖子中提到的 方法。它使用结构性、可视化的方法来绘制子图,而不是令人困惑的数组索引。然而它仍然基于上面提到的后一种选择。

There are three main options in matplotlib to make separate plots within a figure:

  1. subplot: access the axes array and add subplots
  2. gridspec: control the geometric properties of the underlying figure (demo)
  3. subplots: wraps the first two in a convenient api (demo)

The posts so far have addressed the first two options, but they have not mentioned the third, which is the more modern approach and is based on the first two options. See the specific docs Combining two subplots using subplots and GridSpec.


Update

A much nicer improvement may be the provisional subplot_mosaic method mentioned in @Jody Klymak's post. It uses a structural, visual approach to mapping out subplots instead of confusing array indices. However it is still based on the latter options mentioned above.

匿名。 2024-08-29 03:16:27

我能想到两种更灵活的解决方案。

  1. 最灵活的方式:使用subplot_mosaic
f, axes = plt.subplot_mosaic('AAB;CDD;EEE')
# axes = {'A': ..., 'B': ..., ...}

效果:

subplot_mosaic图片

  1. 使用子图gridspec_kw。虽然当不同的行需要不同的宽度比例时也很不方便。
f, (a0, a1) = plt.subplots(1, 2, gridspec_kw={'width_ratios': [2, 1]})

效果:

subplots图片

其他答案的 subplot 方法有点僵化,IMO。例如,您无法轻松创建宽度比为 1:2 和 2:1 的两行。但是,例如,当您需要覆盖子图的某些布局时,它会有所帮助。

I can think of 2 more flexible solutions.

  1. The most flexible way: using subplot_mosaic.
f, axes = plt.subplot_mosaic('AAB;CDD;EEE')
# axes = {'A': ..., 'B': ..., ...}

Effect:

subplot_mosaic picture

  1. Using gridspec_kw of subplots. Although it is also inconvenient when different rows need different width ratios.
f, (a0, a1) = plt.subplots(1, 2, gridspec_kw={'width_ratios': [2, 1]})

Effect:

subplots picture

The subplot method of other answers is kind of rigid, IMO. For example, you cannot create two rows with width ratios being 1:2 and 2:1 easily. However, it can help when you need to overwrite some layout of subplots, for example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文