如何在matplotlib中获得多个子图?

bug*_*syb 116 python matplotlib subplot

我对这段代码的工作原理有点困惑:

fig, axes = plt.subplots(nrows=2, ncols=2)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,无花果轴如何工作?它有什么作用?

为什么这不能做同样的事情:

fig = plt.figure()
axes = fig.subplots(nrows=2, ncols=2)
Run Code Online (Sandbox Code Playgroud)

谢谢

小智 156

有几种方法可以做到这一点.该subplots方法创建图形以及随后存储在ax数组中的子图.例如:

import matplotlib.pyplot as plt

x = range(10)
y = range(10)

fig, ax = plt.subplots(nrows=2, ncols=2)

for row in ax:
    for col in row:
        col.plot(x, y)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

但是,这样的东西也会起作用,虽然你创建了一个包含子图的图形,然后在它们之上添加,但它并不那么"干净":

fig = plt.figure()

plt.subplot(2, 2, 1)
plt.plot(x, y)

plt.subplot(2, 2, 2)
plt.plot(x, y)

plt.subplot(2, 2, 3)
plt.plot(x, y)

plt.subplot(2, 2, 4)
plt.plot(x, y)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 而不是'plot(x,y)`我的绘图来自用户定义的函数,它使用networkx创建图形.如何使用它? (4认同)
  • 您可以先通过“ axn = ax.flatten()”再将“ for axn中的轴”减少为两个for循环:axes.plot(x,y)` (2认同)

Kha*_*oti 32

import matplotlib.pyplot as plt

fig, ax = plt.subplots(2, 2)

ax[0, 0].plot(range(10), 'r') #row=0, col=0
ax[1, 0].plot(range(10), 'b') #row=1, col=0
ax[0, 1].plot(range(10), 'g') #row=0, col=1
ax[1, 1].plot(range(10), 'k') #row=1, col=1
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • ax 实际上是一个 numpy 数组。Fig 是 `matplotlib.figure.Figure` 类,通过它你可以对绘制的图形进行很多操作。例如,您可以将颜色条添加到特定的子图,您可以更改所有子图后面的背景颜色。您可以修改这些子图的布局或向其中添加新的小斧头。最好您可能希望所有子图都有一个主标题,可以通过“fig.suptitle(title)”方法获得。最后,一旦您对情节感到满意,您可以使用“fig.savefig”方法保存它。@Leevo (7认同)
  • 我知道什么是“ax”,但不知道什么是“fig”。这些是什么? (4认同)

Col*_*ony 15

  • 您也可以在子图调用中打开轴的包装

  • 并设置是否要在子图之间共享x和y轴

像这样:

import matplotlib.pyplot as plt
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, sharex=True, sharey=True)
ax1.plot(range(10), 'r')
ax2.plot(range(10), 'b')
ax3.plot(range(10), 'g')
ax4.plot(range(10), 'k')
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


Diz*_*ahi 10

阅读文档:matplotlib.pyplot.subplots

pyplot.subplots()返回一个元组fig, ax,使用符号将其解压缩为两个变量

fig, axes = plt.subplots(nrows=2, ncols=2)
Run Code Online (Sandbox Code Playgroud)

代码

fig = plt.figure()
axes = fig.subplots(nrows=2, ncols=2)
Run Code Online (Sandbox Code Playgroud)

不起作用,因为subplots()函数pyplot不是对象的成员Figure.


Imp*_*est 9

您可能对以下事实感兴趣:从matplotlib 2.1版开始,问题的第二个代码也很好用。

更改日志

Figure类现在具有subplots方法。Figure类现在具有subplots()方法,其行为与pyplot.subplots()相同,但在现有的地物上。

例:

import matplotlib.pyplot as plt

fig = plt.figure()
axes = fig.subplots(nrows=2, ncols=2)

plt.show()
Run Code Online (Sandbox Code Playgroud)


Tre*_*ney 9

子图与pandas

  • 这个答案适用于 的子图pandas,它用作matplotlib默认的绘图后端。
  • 以下是创建以 a 开头的子图的四个选项pandas.DataFrame
    • 实现 1. 和 2. 适用于宽格式的数据,为每列创建子图。
    • 实现 3. 和 4. 适用于长格式的数据,为列中的每个唯一值创建子图。
  • 测试于python 3.8.11, pandas 1.3.2, matplotlib 3.4.3,seaborn 0.11.2

进口和数据

import seaborn as sns  # data only
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# wide dataframe
df = sns.load_dataset('planets').iloc[:, 2:5]

   orbital_period   mass  distance
0         269.300   7.10     77.40
1         874.774   2.21     56.95
2         763.000   2.60     19.84
3         326.030  19.40    110.62
4         516.220  10.50    119.47

# long dataframe
dfm = sns.load_dataset('planets').iloc[:, 2:5].melt()

         variable    value
0  orbital_period  269.300
1  orbital_period  874.774
2  orbital_period  763.000
3  orbital_period  326.030
4  orbital_period  516.220
Run Code Online (Sandbox Code Playgroud)

1.subplots=Truelayout, 对于每列

axes = df.plot(kind='density', subplots=True, layout=(2, 2), sharex=False, figsize=(10, 6))

# extract the figure object; only used for tight_layout in this example
fig = axes[0][0].get_figure() 

# set the individual titles
for ax, title in zip(axes.ravel(), df.columns):
    ax.set_title(title)
fig.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)

2. plt.subplots,对于每一列

  • Axes创建一个with数组matplotlib.pyplot.subplots,然后将axes[i, j]or传递axes[n]ax参数。
    • 此选项使用pandas.DataFrame.plot,但可以使用其他axes级别绘图调用作为替代(例如sns.kdeplotplt.plot等)
    • 使用或将 的子图数组折叠Axes成一维是最简单的。参见.ravel.flatten.ravel.flatten
    • 任何应用于每个axes、需要迭代的变量都与.zip(例如colsaxescolorspalette等)组合。每个对象的长度必须相同。
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 6))  # define the figure and subplots
axes = axes.ravel()  # array to 1D
cols = df.columns  # create a list of dataframe columns to use
colors = ['tab:blue', 'tab:orange', 'tab:green']  # list of colors for each subplot, otherwise all subplots will be one color

for col, color, ax in zip(cols, colors, axes):
    df[col].plot(kind='density', ax=ax, color=color, label=col, title=col)
    ax.legend()
    
fig.delaxes(axes[3])  # delete the empty subplot
fig.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)

1. 和 2. 的结果。

在此输入图像描述

3. plt.subplots,对于每个组.groupby

  • 这与 2. 类似,只不过它是 zipcoloraxes指向一个.groupby对象。
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 6))  # define the figure and subplots
axes = axes.ravel()  # array to 1D
dfg = dfm.groupby('variable')  # get data for each unique value in the first column
colors = ['tab:blue', 'tab:orange', 'tab:green']  # list of colors for each subplot, otherwise all subplots will be one color

for (group, data), color, ax in zip(dfg, colors, axes):
    data.plot(kind='density', ax=ax, color=color, title=group, legend=False)

fig.delaxes(axes[3])  # delete the empty subplot
fig.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

4.seaborn人物级情节

  • 使用seaborn图形级图,并使用colrow参数。seaborn是一个高级 API matplotlib。请参阅seaborn:API 参考
p = sns.displot(data=dfm, kind='kde', col='variable', col_wrap=2, x='value', hue='variable',
                facet_kws={'sharey': False, 'sharex': False}, height=3.5, aspect=1.75)
sns.move_legend(p, "upper left", bbox_to_anchor=(.55, .45))
Run Code Online (Sandbox Code Playgroud)


uke*_*emi 6

按顺序迭代所有子图:

fig, axes = plt.subplots(nrows, ncols)

for ax in axes.flatten():
    ax.plot(x,y)
Run Code Online (Sandbox Code Playgroud)

访问特定索引:

for row in range(nrows):
    for col in range(ncols):
        axes[row,col].plot(x[row], y[col])
Run Code Online (Sandbox Code Playgroud)


Tre*_*ney 5

将数组转换axes为一维

\n
    \n
  • 使用 生成子图plt.subplots(nrows, ncols)(其中nrows 和 ncols大于 1)会返回嵌套的<AxesSubplot:>对象数组。\n
      \n
    • 在 或的axes情况下,\xe2\x80\x99s 不需要展平,因为已经是一维了,这是默认参数的结果nrows=1ncols=1axessqueeze=True
    • \n
    \n
  • \n
  • 访问对象的最简单方法是使用 、 或 将数组转换为一维.ravel().flatten()\ .flatn
      \n
    • .ravel.flatten\n
        \n
      • flatten总是返回一个副本。
      • \n
      • ravel尽可能返回原始数组的视图。
      • \n
      \n
    • \n
    \n
  • \n
  • 一旦 的数组axes转换为一维数组,就有多种绘制方法。
  • \n
  • 这个答案与seaborn轴级图相关,它具有参数ax=(例如sns.barplot(\xe2\x80\xa6, ax=ax[0])。\n\n
  • \n
\n
import matplotlib.pyplot as plt\nimport numpy as np  # sample data only\n\n# example of data\nrads = np.arange(0, 2*np.pi, 0.01)\ny_data = np.array([np.sin(t*rads) for t in range(1, 5)])\nx_data = [rads, rads, rads, rads]\n\n# Generate figure and its subplots\nfig, axes = plt.subplots(nrows=2, ncols=2)\n\n# axes before\narray([[<AxesSubplot:>, <AxesSubplot:>],\n       [<AxesSubplot:>, <AxesSubplot:>]], dtype=object)\n\n# convert the array to 1 dimension\naxes = axes.ravel()\n\n# axes after\narray([<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>],\n      dtype=object)\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 迭代展平数组\n
      \n
    • 如果子图多于数据,这将导致IndexError: list index out of range\n
        \n
      • 请尝试选项 3.,或者选择轴的子集(例如axes[:-2]
      • \n
      \n
    • \n
    \n
  2. \n
\n
for i, ax in enumerate(axes):\n    ax.plot(x_data[i], y_data[i])\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 通过索引访问每个轴
  2. \n
\n
axes[0].plot(x_data[0], y_data[0])\naxes[1].plot(x_data[1], y_data[1])\naxes[2].plot(x_data[2], y_data[2])\naxes[3].plot(x_data[3], y_data[3])\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 索引数据和轴
  2. \n
\n
for i in range(len(x_data)):\n    axes[i].plot(x_data[i], y_data[i])\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. zip将轴和数据放在一起,然后迭代元组列表。
  2. \n
\n
for ax, x, y in zip(axes, x_data, y_data):\n    ax.plot(x, y)\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n

在此输入图像描述

\n
\n
    \n
  • 一个选项是将每个轴分配给一个变量fig, (ax1, ax2, ax3) = plt.subplots(1, 3)。然而,正如所写,这只适用于 或 的nrows=1情况ncols=1。这是基于 返回的数组的形状plt.subplots,并且很快就会变得很麻烦。\n
      \n
    • fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)对于 2 x 2 数组。
    • \n
    • 这对于两个子图(例如:fig, (ax1, ax2) = plt.subplots(1, 2)fig, (ax1, ax2) = plt.subplots(2, 1))最有用。对于更多子图,展平和迭代轴数组会更有效。
    • \n
    \n
  • \n
\n