如何绘制多个子图

2024-11-19 08:39:00
admin
原创
11
摘要:问题描述:我对这段代码的工作原理有点困惑:fig, axes = plt.subplots(nrows=2, ncols=2) plt.show() 在这种情况下,无花果轴如何工作?它起什么作用?为什么这不能起到同样的作用:fig = plt.figure() axes = fig.subplots(nrow...

问题描述:

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

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

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

为什么这不能起到同样的作用:

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

解决方案 1:

有几种方法可以做到这一点。该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()

在此处输入图片描述

但是,类似这样的方法也可以,但是它不是那么“干净”,因为您正在创建一个带有子图的图形,然后在它们之上添加:

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()

在此处输入图片描述

解决方案 2:

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()

在此处输入图片描述

解决方案 3:

  • 您还可以在子图调用中解压轴

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

像这样:

import matplotlib.pyplot as plt
# fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, sharex=True, sharey=True)
fig, axes = plt.subplots(nrows=2, ncols=2, sharex=True, sharey=True)
ax1, ax2, ax3, ax4 = axes.flatten()

ax1.plot(range(10), 'r')
ax2.plot(range(10), 'b')
ax3.plot(range(10), 'g')
ax4.plot(range(10), 'k')
plt.show()

2 x 2 图

解决方案 4:

您可能对这样一个事实感兴趣:从 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()

解决方案 5:

阅读文档:matplotlib.pyplot.subplots

pyplot.subplots()返回fig, ax使用符号解包为两个变量的元组

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

代码:

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

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

解决方案 6:

子图pandas

  • 这个答案适用于带有的子图pandas,它用作matplotlib默认绘图后端。

  • 以下是创建子图的四个选项,以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

1.subplots=Truelayout,对于每一列

  • 使用参数subplots=Truelayout=(rows, cols)`pandas.DataFrame.plot`

  • 此示例使用kind='density',但 有不同的选项kind,这适用于所有选项。如果不指定kind,则默认为线图。

  • axAxesSubplot返回的数组pandas.DataFrame.plot

  • 如果需要,
    请参阅如何获取Figure对象。

    • 如何保存熊猫子图

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()

2. plt.subplots,对于每一列

  • 创建一个Axes带有的数组matplotlib.pyplot.subplots,然后将axes[i, j]或传递axes[n]ax参数。

    • 该选项使用pandas.DataFrame.plot,但可以使用其他axes级别绘图调用作为替代(例如sns.kdeplotplt.plot等)。

    • 最简单的方法是使用或 将的子图数组折叠Axes成一维。请参阅vs。.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()

1. 和 2 的结果。

在此处输入图片描述

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

  • 这与 2. 类似,只是它将拉链color拉到物体axes.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()

在此处输入图片描述

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))

解决方案 7:

依次迭代所有子图:

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

for ax in axes.flatten():
    ax.plot(x,y)

访问特定索引:

for row in range(nrows):
    for col in range(ncols):
        axes[row,col].plot(x[row], y[col])

解决方案 8:

将数组转换axes为一维

  • 使用 生成子图plt.subplots(nrows, ncols),其中nrows 和 ncols大于 1,返回一个嵌套的<AxesSubplot:>对象数组。

    • axesnrows=1或 的情况下,没有必要展平ncols=1,因为axes已经是一维的,这是默认参数的结果squeeze=True

  • 访问对象的最简单方法是使用 、 或 将数组转换为.ravel()1.flatten().flat

    • .ravel对阵.flatten

      • flatten总是返回一份副本。

      • ravel尽可能返回原始数组的视图。

  • 一旦将数组axes转换为一维,就有多种绘图方式。

  • 这个答案与 seaborn 轴级图相关,它们具有ax=参数(例如sns.barplot(…, ax=ax[0])

    • seaborn是 的高级 API matplotlib。请参阅图形级与轴级函数,seaborn 未在定义的子图内绘图

import matplotlib.pyplot as plt
import numpy as np  # sample data only

# example of data
rads = np.arange(0, 2*np.pi, 0.01)
y_data = np.array([np.sin(t*rads) for t in range(1, 5)])
x_data = [rads, rads, rads, rads]

# Generate figure and its subplots
fig, axes = plt.subplots(nrows=2, ncols=2)

# axes before
array([[<AxesSubplot:>, <AxesSubplot:>],
       [<AxesSubplot:>, <AxesSubplot:>]], dtype=object)

# convert the array to 1 dimension
axes = axes.ravel()

# axes after
array([<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>],
      dtype=object)
  1. 迭代扁平数组

    • 如果子图数量多于数据数量,则会导致IndexError: list index out of range

      • 请尝试选项 3.,或者选择轴的子集(例如axes[:-2]

for i, ax in enumerate(axes):
    ax.plot(x_data[i], y_data[i])
  1. 通过索引访问每个轴

axes[0].plot(x_data[0], y_data[0])
axes[1].plot(x_data[1], y_data[1])
axes[2].plot(x_data[2], y_data[2])
axes[3].plot(x_data[3], y_data[3])
  1. 索引数据和轴

for i in range(len(x_data)):
    axes[i].plot(x_data[i], y_data[i])
  1. zip将轴和数据放在一起,然后遍历元组列表。

for ax, x, y in zip(axes, x_data, y_data):
    ax.plot(x, y)

输出

在此处输入图片描述


  • 一种选择是将每个轴分配给一个变量。fig, (ax1, ax2, ax3) = plt.subplots(1, 3)但是,正如所写,这仅适用于nrows=1或的情况ncols=1。这是基于返回的数组的形状plt.subplots,并且很快就会变得繁琐。

    • fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)对于 2 x 2 数组。

    • fig, (ax1, ax2) = plt.subplots(1, 2)这对于两个子图(例如:或)最有用fig, (ax1, ax2) = plt.subplots(2, 1)。对于更多子图,展平并遍历轴数组更有效。

解决方案 9:

您可以使用以下内容:

import numpy as np
import matplotlib.pyplot as plt

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

for i, ax in enumerate(fig.axes):
  ax.plot(np.sin(np.linspace(0,2*np.pi,100) + np.pi/2*i))

代码结果:图

或者,使用plt.subplot返回的第二个变量:

fig, ax_mat = plt.subplots(nrows=2, ncols=2)
for i, ax in enumerate(ax_mat.flatten()):
    ...

ax_mat是一个轴矩阵。其形状为 nrows x ncols。

解决方案 10:

add_subplot您可以在以下位置使用该方法matplotlib

funcs = [np.cos, np.sin, np.tan, np.arctan, np.exp, np.log]
x = np.linspace(1, 10, 100)

fig = plt.figure(figsize=(10, 5))

# iterate over the function list and add a subplot for each function
for idx, func in enumerate(funcs, start=1):  
    ax = fig.add_subplot(2, 3, idx) # plot with 2 rows and 3 columns
    ax.plot(x, func(x))
    ax.set_title(func.__name__)

# add spacing between subplots
fig.tight_layout()

在此处输入图片描述

解决方案 11:

这是一个简单的解决方案

fig, ax = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=False)
for sp in fig.axes:
    sp.plot(range(10))

输出

解决方案 12:

如果您确实想使用循环,请执行以下操作:

def plot(data):
    fig = plt.figure(figsize=(100, 100))
    for idx, k in enumerate(data.keys(), 1):
        x, y = data[k].keys(), data[k].values
        plt.subplot(63, 10, idx)
        plt.bar(x, y)  
    plt.show()

解决方案 13:

另一个简洁的解决方案是:

// set up structure of plots
f, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(20,10))

// for plot 1
ax1.set_title('Title A')
ax1.plot(x, y)

// for plot 2
ax2.set_title('Title B')
ax2.plot(x, y)

// for plot 3
ax3.set_title('Title C')
ax3.plot(x,y)
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用