Noter
Cliquez ici pour télécharger l'exemple de code complet
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_mosaic
et 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 GridSpec
et 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]
subplot
ouFigure.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' Axes
objets. 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()')
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()')
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')
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_toolkits
permet également ImageGrid
d'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')
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_mosaic
en 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()')
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
GridSpec
ou subplot2grid
.
Largeurs ou hauteurs variables dans une grille #
Les deux subplots
et subplot_mosaic
permettent 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 à subplots
et
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()')
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]')
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')
Il est également possible d'imbriquer des axes à l' subplot_mosaic
aide 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 suptitle
et supxlabel
, etc. Il s'agit plutôt d'un emballage pratique autour de la subgridspec
méthode décrite ci-dessous.
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 GridSpec
et 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')
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')
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_layout
ou
Figure.tight_layout
qui 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 à subplots
et
subplot_mosaic
en 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')
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' subfigures
utilisation
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')
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()
Plus de lecture #
Plus de détails sur la mosaïque de sous-parcelles .
Plus de détails sur la mise en page contrainte , utilisée pour aligner l'espacement dans la plupart de ces exemples.
Références
L'utilisation des fonctions, méthodes, classes et modules suivants est illustrée dans cet exemple :
Durée totale d'exécution du script : (0 minutes 13,006 secondes)