HOWTO · Matplotlib

Comment créer une légende unique pour toutes les sous-parcelles dans Matplotlib

La méthode `fig.legend()` de Matplotlib crée une légende au niveau de la figure entière, tandis que `ax.legend()` crée une légende pour un seul objet Axes. Lorsque toutes les sous-parcelles utilisent les mêmes séries et les mêmes étiquettes, les handles et les étiquettes d’un seul objet Axes peuvent être réutilisés.

Sur cette page

Utilisez fig.legend() pour associer une légende à l’ensemble de la figure Matplotlib. Lorsque chaque sous-parcelle affiche les mêmes séries avec les mêmes étiquettes, réutilisez les handles et les étiquettes d’un seul objet Axes. Si les sous-parcelles affichent des séries différentes, récupérez les handles et les étiquettes de chaque objet Axes, puis transmettez les deux listes à la légende de la figure. Contrairement à ax.legend(), qui crée une légende pour un seul objet Axes, fig.legend() permet de créer une légende au niveau de la figure entière.

Les exemples ci-dessous utilisent Matplotlib pour créer les figures. Le premier affiche également les étiquettes récupérées pour sa légende commune. Les étiquettes visibles dans les exemples de code restent en anglais, car le code est conservé à l’identique.

Créer une légende commune au niveau de la figure lorsque les sous-parcelles utilisent les mêmes étiquettes

Si chaque sous-parcelle représente les mêmes séries avec les mêmes étiquettes, une seule d’entre elles fournit déjà les entrées nécessaires à une légende commune. L’exemple ci-dessous utilise deux mesures d’échelles différentes, toutes deux étiquetées measurement. Comme l’étiquette et sa signification sont identiques, les handles du premier objet Axes suffisent. Associez la légende à fig, au lieu d’appeler legend() sur chaque objet Axes, pour ne l’afficher qu’une seule fois dans la figure. L’étiquette measurement affichée par l’exemple reste en anglais dans le code inchangé.

Exécutez cet exemple :

import matplotlib

matplotlib.use("Agg")
import logging

# Ignore only Matplotlib's benign cold-start cache notice; other diagnostics
# remain visible on stderr.
class _FontCacheNoticeFilter(logging.Filter):
    def filter(self, record):
        return "Matplotlib is building the font cache; this may take a moment." not in record.getMessage()


logging.getLogger("matplotlib.font_manager").addFilter(_FontCacheNoticeFilter())
import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 1, figsize=(6, 4))
x = [0, 1, 2]

for ax, scale in zip(axes, [1, 2]):
    ax.plot(x, [scale * value for value in x], label="measurement")

handles, labels = axes[0].get_legend_handles_labels()
fig.legend(handles, labels, loc="upper center")
fig.tight_layout(rect=(0, 0, 1, 0.9))
print("Legend entries:", labels)
plt.show()
Legend entries: ['measurement']

get_legend_handles_labels() renvoie deux listes associées pour les artistes étiquetés de cet objet Axes. Cette méthode est concise, mais elle ne représente que les séries présentes sur l’objet Axes choisi. Si une autre sous-parcelle comporte une étiquette ou une série différente, utilisez la méthode qui collecte les entrées de tous les objets Axes, dans la section suivante.

Récupérer les handles et les étiquettes de chaque objet Axes lorsque le contenu des sous-parcelles diffère

Lorsque les sous-parcelles contiennent des lignes différentes avec des étiquettes distinctes, récupérez les handles et les étiquettes de chaque objet Axes dans la même boucle. Les listes restent associées par position : le handle à l’indice i correspond à l’étiquette à l’indice i. Le code ci-dessous produit deux entrées dans la légende, une pour chaque ligne. Les étiquettes visibles dans le code inchangé restent en anglais.

Exécutez cet exemple :

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2, figsize=(7, 3))
axes[0].plot([0, 1, 2], [0, 1, 4], label="quadratic")
axes[1].plot([0, 1, 2], [0, 1, 2], label="linear")

handles, labels = [], []
for ax in axes:
    ax_handles, ax_labels = ax.get_legend_handles_labels()
    handles.extend(ax_handles)
    labels.extend(ax_labels)

fig.legend(handles, labels, loc="upper center", ncol=2)
fig.tight_layout(rect=(0, 0, 1, 0.88))
plt.show()

Cette méthode récupère les artistes étiquetés de chaque objet Axes ; une même étiquette peut donc apparaître plusieurs fois. Si les entrées répétées désignent la même notion, sélectionnez un seul handle par étiquette souhaitée avant d’appeler fig.legend(). À l’inverse, conservez les étiquettes distinctes lorsque les lecteurs doivent pouvoir différencier les séries. Pour ne montrer qu’un sous-ensemble, transmettez uniquement les handles et les étiquettes correspondants : la légende n’a pas à inclure toutes les lignes tracées.

Positionner et mettre en forme la légende au niveau de la figure

L’argument loc détermine quel point de la légende s’aligne sur son ancre. Par exemple, fig.legend(..., loc="upper center") centre la légende en haut de la figure. Pour définir précisément l’ancre, utilisez bbox_to_anchor ; dans le cas d’une légende de figure, ses coordonnées sont relatives à la figure. Par exemple, fig.legend(handles, labels, loc="upper center", bbox_to_anchor=(0.5, 1.02)) place la légende juste au-dessus du bord supérieur. Modifiez les valeurs de l’ancre pour la déplacer, et réservez-lui de l’espace avec fig.tight_layout(rect=(0, 0, 1, 0.9)) ou fig.subplots_adjust(top=0.82) afin qu’elle ne recouvre pas le contenu des sous-parcelles.

La mise en forme de la légende utilise les mêmes options courantes que les autres légendes Matplotlib. Transmettez à fig.legend() des valeurs telles que fontsize=9, frameon=False ou facecolor="white" pour régler la taille du texte, le cadre ou son arrière-plan. Lorsqu’une figure comporte une légende située à l’extérieur de ses limites, fig.savefig("plot.png", bbox_inches="tight") peut inclure cette légende dans l’image enregistrée.

Questions fréquentes sur une légende au niveau de la figure

Quelle est la différence entre ax.legend() et fig.legend() ? ax.legend() est rattachée à un objet Axes particulier. fig.legend() est rattachée à la Figure et peut réunir des entrées provenant d’un ou de plusieurs objets Axes.

Comment créer une légende unique lorsque toutes les sous-parcelles utilisent les mêmes étiquettes ? Récupérez les handles et les étiquettes d’un objet Axes représentatif, puis transmettez-les à fig.legend(). Cette méthode convient si cet objet Axes comporte les mêmes séries étiquetées que les autres sous-parcelles.

Comment n’inclure que certaines lignes ? Conservez les handles et les étiquettes souhaités dans deux listes associées, puis transmettez ces listes à fig.legend(). En présence d’étiquettes répétées, vérifiez si les entrées représentent la même série avant de supprimer les doublons.

Comment éviter que la légende recouvre les graphiques ? Placez-la dans une marge de la figure à l’aide de loc et de bbox_to_anchor, puis réservez-lui de l’espace dans la disposition des sous-parcelles. Si elle se trouve à l’extérieur du canevas, utilisez une boîte englobante ajustée lors de l’enregistrement pour éviter qu’elle soit coupée.