Organiser plusieurs axes dans une figure #

Souvent, plusieurs axes sont nécessaires sur une figure à la fois, généralement organisés en une grille régulière. Matplotlib dispose d'une variété d'outils pour travailler avec des grilles d'axes qui ont évolué au cours de l'histoire de la bibliothèque. Ici, nous discuterons des outils que nous pensons que les utilisateurs devraient utiliser le plus souvent, des outils qui sous-tendent l'organisation des Axes et mentionnerons certains des outils les plus anciens.

Noter

Matplotlib utilise Axes pour faire référence à la zone de dessin qui contient des données, des axes x et y, des repères, des étiquettes, un titre, etc. Voir Parties d'une figure pour plus de détails. Un autre terme souvent utilisé est "sous-parcelle", qui fait référence à un Axes qui se trouve dans une grille avec d'autres objets Axes.

Aperçu #

Créer des combinaisons d'axes en forme de grille #

subplots

La fonction principale utilisée pour créer des figures et une grille d'axes. Il crée et place tous les axes sur la figure en même temps et renvoie un tableau d'objets avec des poignées pour les axes de la grille. Voir Figure.subplots.

ou

subplot_mosaic

Un moyen simple de créer des figures et une grille d'axes, avec la flexibilité supplémentaire que les axes peuvent également s'étendre sur des lignes ou des colonnes. Les axes sont renvoyés dans un dictionnaire étiqueté au lieu d'un tableau. Voir aussi Figure.subplot_mosaicet Composition de figures complexes et sémantiques .

Parfois, il est naturel d'avoir plus d'un groupe distinct de grilles Axes, auquel cas Matplotlib a le concept deSubFigure :

SubFigure

Une figure virtuelle dans une figure.

Outils sous-jacents #

Sous-jacents à ceux-ci se trouvent le concept de a GridSpecet a SubplotSpec:

GridSpec

Spécifie la géométrie de la grille dans laquelle un sous-parc sera placé. Le nombre de lignes et le nombre de colonnes de la grille doivent être définis. En option, les paramètres de mise en page de la sous-parcelle (par exemple, gauche, droite, etc.) peuvent être réglés.

SubplotSpec

Spécifie l'emplacement de la sous-parcelle dans le fichier GridSpec.

Ajout d'axes simples à la fois #

Les fonctions ci-dessus créent tous les axes en un seul appel de fonction. Il est également possible d'ajouter des axes un par un, et c'était à l'origine ainsi que Matplotlib fonctionnait. Cela est généralement moins élégant et flexible, bien que parfois utile pour un travail interactif ou pour placer un Axes dans un emplacement personnalisé :

add_axes

Ajoute un seul axe à un emplacement spécifié par en fractions de largeur ou de hauteur de figure.[left, bottom, width, height]

subplotouFigure.add_subplot

Ajoute une seule sous-parcelle sur une figure, avec une indexation basée sur 1 (héritée de Matlab). Les colonnes et les lignes peuvent être étendues en spécifiant une plage de cellules de grille.

subplot2grid

Similaire à pyplot.subplot, mais utilise une indexation basée sur 0 et un découpage Python à deux dimensions pour choisir les cellules.

Méthodes de haut niveau pour créer des grilles #

Grille de base 2x2 #

Nous pouvons créer une grille d'axes de base 2 par 2 en utilisant subplots. Il renvoie une Figure instance et un tableau d' Axesobjets. Les objets Axes peuvent être utilisés pour accéder à des méthodes permettant de placer des artistes sur les Axes ; ici nous utilisons annotate, mais d'autres exemples pourraient être plot, pcolormesh, etc.

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(5.5, 3.5),
                        layout="constrained")
# add an artist, in this case a nice label in the middle...
for row in range(2):
    for col in range(2):
        axs[row, col].annotate(f'axs[{row}, {col}]', (0.5, 0.5),
                               transform=axs[row, col].transAxes,
                               ha='center', va='center', fontsize=18,
                               color='darkgrey')
fig.suptitle('plt.subplots()')
plt.subplots()
Text(0.5, 0.9880942857142857, 'plt.subplots()')

Nous allons annoter beaucoup d'axes, alors encapsulons l'annotation, plutôt que d'avoir ce gros morceau de code d'annotation à chaque fois que nous en avons besoin :

def annotate_axes(ax, text, fontsize=18):
    ax.text(0.5, 0.5, text, transform=ax.transAxes,
            ha="center", va="center", fontsize=fontsize, color="darkgrey")

Le même effet peut être obtenu avec subplot_mosaic, mais le type de retour est un dictionnaire au lieu d'un tableau, où l'utilisateur peut donner aux clés des significations utiles. Ici, nous fournissons deux listes, chaque liste représentant une ligne et chaque élément de la liste une clé représentant la colonne.

fig, axd = plt.subplot_mosaic([['upper left', 'upper right'],
                               ['lower left', 'lower right']],
                              figsize=(5.5, 3.5), layout="constrained")
for k in axd:
    annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
plt.subplot_mosaic()
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')

Grilles de rapport d'aspect fixe Axes #

Les axes à rapport hauteur/largeur fixe sont courants pour les images ou les cartes. Cependant, ils présentent un défi pour la mise en page car deux ensembles de contraintes sont imposés sur la taille des Axes - qu'ils s'intègrent dans la figure et qu'ils ont un rapport d'aspect défini. Cela conduit à de grands écarts entre les Axes par défaut :

fig, axs = plt.subplots(2, 2, layout="constrained", figsize=(5.5, 3.5))
for ax in axs.flat:
    ax.set_aspect(1)
fig.suptitle('Fixed aspect Axes')
Axes à aspect fixe
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes')

Une façon de résoudre ce problème consiste à modifier l'aspect de la figure pour qu'il soit proche du rapport d'aspect des axes, mais cela nécessite des essais et des erreurs. Matplotlib fournit également layout="compressed", qui fonctionnera avec des grilles simples pour réduire les écarts entre les axes. (Le mpl_toolkitspermet également ImageGridd'accomplir un effet similaire, mais avec une classe Axes non standard).

fig, axs = plt.subplots(2, 2, layout="compressed", figsize=(5.5, 3.5))
for ax in axs.flat:
    ax.set_aspect(1)
fig.suptitle('Fixed aspect Axes: compressed')
Axes d'aspect fixe : compressés
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes: compressed')

Axes s'étendant sur des lignes ou des colonnes dans une grille #

Parfois, nous voulons que les axes s'étendent sur des lignes ou des colonnes de la grille. Il existe en fait plusieurs façons d'y parvenir, mais la plus pratique consiste probablement à utiliser subplot_mosaicen répétant l'une des touches :

fig, axd = plt.subplot_mosaic([['upper left', 'right'],
                               ['lower left', 'right']],
                              figsize=(5.5, 3.5), layout="constrained")
for k in axd:
    annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
plt.subplot_mosaic()
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')

Voir ci-dessous pour la description de la façon de faire la même chose en utilisant GridSpecou subplot2grid.

Largeurs ou hauteurs variables dans une grille #

Les deux subplotset subplot_mosaicpermettent aux lignes de la grille d'avoir des hauteurs différentes et aux colonnes d'avoir des largeurs différentes à l'aide de l' argument de mot-clé gridspec_kw . Les paramètres d'espacement acceptés par GridSpec peuvent être passés à subplotset subplot_mosaic:

gs_kw = dict(width_ratios=[1.4, 1], height_ratios=[1, 2])
fig, axd = plt.subplot_mosaic([['upper left', 'right'],
                               ['lower left', 'right']],
                              gridspec_kw=gs_kw, figsize=(5.5, 3.5),
                              layout="constrained")
for k in axd:
    annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
plt.subplot_mosaic()
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')

Dispositions d'axes imbriqués #

Parfois, il est utile d'avoir deux ou plusieurs grilles d'axes qui n'ont pas besoin d'être liées les unes aux autres. Le moyen le plus simple d'y parvenir est d'utiliser Figure.subfigures. Notez que les dispositions des sous-figures sont indépendantes, de sorte que les épines des axes de chaque sous-figure ne sont pas nécessairement alignées. Voir ci-dessous pour une manière plus détaillée d'obtenir le même effet avec GridSpecFromSubplotSpec.

fig = plt.figure(layout="constrained")
subfigs = fig.subfigures(1, 2, wspace=0.07, width_ratios=[1.5, 1.])
axs0 = subfigs[0].subplots(2, 2)
subfigs[0].set_facecolor('0.9')
subfigs[0].suptitle('subfigs[0]\nLeft side')
subfigs[0].supxlabel('xlabel for subfigs[0]')

axs1 = subfigs[1].subplots(3, 1)
subfigs[1].suptitle('subfigs[1]')
subfigs[1].supylabel('ylabel for subfigs[1]')
disposer les axes
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')

Il est également possible d'imbriquer des axes à l' subplot_mosaicaide de listes imbriquées. Cette méthode n'utilise pas de sous-figures, comme ci-dessus, et n'a donc pas la possibilité d'ajouter par sous-figure suptitleet supxlabel, etc. Il s'agit plutôt d'un emballage pratique autour de la subgridspec méthode décrite ci-dessous.

inner = [['innerA'],
         ['innerB']]
outer = [['upper left',  inner],
          ['lower left', 'lower right']]

fig, axd = plt.subplot_mosaic(outer, layout="constrained")
for k in axd:
    annotate_axes(axd[k], f'axd["{k}"]')
disposer les axes

Méthodes de grille de bas niveau et avancées #

En interne, la disposition d'une grille d'axes est contrôlée en créant des instances de GridSpecet SubplotSpec. GridSpec définit une grille de cellules (éventuellement non uniforme). L' indexation dans le GridSpec renvoie un SubplotSpec qui couvre une ou plusieurs cellules de grille et peut être utilisé pour spécifier l'emplacement d'un Axes.

Les exemples suivants montrent comment utiliser des méthodes de bas niveau pour organiser des axes à l'aide d'objets GridSpec .

Grille de base 2x2 #

On peut réaliser une grille 2x2 de la même manière que :plt.subplots(2, 2)

fig = plt.figure(figsize=(5.5, 3.5), layout="constrained")
spec = fig.add_gridspec(ncols=2, nrows=2)

ax0 = fig.add_subplot(spec[0, 0])
annotate_axes(ax0, 'ax0')

ax1 = fig.add_subplot(spec[0, 1])
annotate_axes(ax1, 'ax1')

ax2 = fig.add_subplot(spec[1, 0])
annotate_axes(ax2, 'ax2')

ax3 = fig.add_subplot(spec[1, 1])
annotate_axes(ax3, 'ax3')

fig.suptitle('Manually added subplots using add_gridspec')
Sous-parcelles ajoutées manuellement à l'aide de add_gridspec
Text(0.5, 0.9880942857142857, 'Manually added subplots using add_gridspec')

Axes couvrant des rangées ou des grilles dans une grille #

Nous pouvons indexer le tableau spec en utilisant la syntaxe de tranche NumPy et les nouveaux axes couvriront la tranche. Ce serait la même chose que :fig, axd = plt.subplot_mosaic([['ax0', 'ax0'], ['ax1', 'ax2']], ...)

fig = plt.figure(figsize=(5.5, 3.5), layout="constrained")
spec = fig.add_gridspec(2, 2)

ax0 = fig.add_subplot(spec[0, :])
annotate_axes(ax0, 'ax0')

ax10 = fig.add_subplot(spec[1, 0])
annotate_axes(ax10, 'ax10')

ax11 = fig.add_subplot(spec[1, 1])
annotate_axes(ax11, 'ax11')

fig.suptitle('Manually added subplots, spanning a column')
Sous-parcelles ajoutées manuellement, couvrant une colonne
Text(0.5, 0.9880942857142857, 'Manually added subplots, spanning a column')

Ajustements manuels à une mise en page GridSpec #

Lorsqu'un GridSpec est explicitement utilisé, vous pouvez ajuster les paramètres de mise en page des sous-parcelles créées à partir du GridSpec . Notez que cette option n'est pas compatible avec constrained_layoutou Figure.tight_layoutqui ignorent à la fois gauche et droite et ajustent les tailles des sous-parcelles pour remplir la figure. Habituellement, un tel placement manuel nécessite des itérations pour que les étiquettes de coche des axes ne chevauchent pas les axes.

Ces paramètres d'espacement peuvent également être passés à subplotset subplot_mosaicen tant qu'argument gridspec_kw .

fig = plt.figure(layout=None, facecolor='0.9')
gs = fig.add_gridspec(nrows=3, ncols=3, left=0.05, right=0.75,
                      hspace=0.1, wspace=0.05)
ax0 = fig.add_subplot(gs[:-1, :])
annotate_axes(ax0, 'ax0')
ax1 = fig.add_subplot(gs[-1, :-1])
annotate_axes(ax1, 'ax1')
ax2 = fig.add_subplot(gs[-1, -1])
annotate_axes(ax2, 'ax2')
fig.suptitle('Manual gridspec with right=0.75')
Gridspec manuel avec right=0.75
Text(0.5, 0.98, 'Manual gridspec with right=0.75')

Dispositions imbriquées avec SubplotSpec #

Vous pouvez créer une mise en page imbriquée similaire à l' subfiguresutilisation de subgridspec. Ici, les épines des Axes sont alignées.

Notez que ceci est également disponible à partir du plus verbeux gridspec.GridSpecFromSubplotSpec.

fig = plt.figure(layout="constrained")
gs0 = fig.add_gridspec(1, 2)

gs00 = gs0[0].subgridspec(2, 2)
gs01 = gs0[1].subgridspec(3, 1)

for a in range(2):
    for b in range(2):
        ax = fig.add_subplot(gs00[a, b])
        annotate_axes(ax, f'axLeft[{a}, {b}]', fontsize=10)
        if a == 1 and b == 1:
            ax.set_xlabel('xlabel')
for a in range(3):
    ax = fig.add_subplot(gs01[a])
    annotate_axes(ax, f'axRight[{a}, {b}]')
    if a == 2:
        ax.set_ylabel('ylabel')

fig.suptitle('nested gridspecs')
spécifications de grille imbriquées
Text(0.5, 0.99131875, 'nested gridspecs')

Voici un exemple plus sophistiqué de GridSpec imbriqué : Nous créons une grille externe 4x4 avec chaque cellule contenant une grille interne 3x3 d'Axes. Nous décrivons la grille 4x4 extérieure en masquant les épines appropriées dans chacune des grilles 3x3 intérieures.

def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
    return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)

fig = plt.figure(figsize=(8, 8), constrained_layout=False)
outer_grid = fig.add_gridspec(4, 4, wspace=0, hspace=0)

for a in range(4):
    for b in range(4):
        # gridspec inside gridspec
        inner_grid = outer_grid[a, b].subgridspec(3, 3, wspace=0, hspace=0)
        axs = inner_grid.subplots()  # Create all subplots for the inner grid.
        for (c, d), ax in np.ndenumerate(axs):
            ax.plot(*squiggle_xy(a + 1, b + 1, c + 1, d + 1))
            ax.set(xticks=[], yticks=[])

# show only the outside spines
for ax in fig.get_axes():
    ss = ax.get_subplotspec()
    ax.spines.top.set_visible(ss.is_first_row())
    ax.spines.bottom.set_visible(ss.is_last_row())
    ax.spines.left.set_visible(ss.is_first_col())
    ax.spines.right.set_visible(ss.is_last_col())

plt.show()
disposer les axes

Plus de lecture #

Durée totale d'exécution du script : (0 minutes 13,006 secondes)

Galerie générée par Sphinx-Gallery