Annoter efficacement les graphiques Matplotlib

MatplotlibMatplotlibBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Ce laboratoire vous guidera dans l'annotation de graphes avec Matplotlib. Vous allez apprendre à souligner des points d'intérêt spécifiques et à utiliser divers outils visuels pour attirer l'attention sur ces points. Les outils d'annotation et de texte sont essentiels pour communiquer des informations et rendre les graphes plus visuellement attrayants.

Conseils sur la machine virtuelle

Une fois le démarrage de la machine virtuelle terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Carnet de notes pour accéder au carnet Jupyter Notebook pour pratiquer.

Parfois, vous devrez peut-être attendre quelques secondes pour que le carnet Jupyter Notebook ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations du carnet Jupyter Notebook.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez des commentaires après la session, et nous résoudrons rapidement le problème pour vous.

Spécification des points de texte et des points d'annotation

Vous devez spécifier un point d'annotation xy=(x, y) pour annoter ce point. De plus, vous pouvez spécifier un point de texte xytext=(x, y) pour la position du texte de cette annotation. Facultativement, vous pouvez spécifier le système de coordonnées de xy et xytext avec l'une des chaînes suivantes pour xycoords et textcoords (valeur par défaut : 'data') :

  • 'points de figure' : points à partir du coin inférieur gauche de la figure
  • 'pixels de figure' : pixels à partir du coin inférieur gauche de la figure
  • 'fraction de figure' : (0, 0) est le coin inférieur gauche de la figure et (1, 1) est le coin supérieur droit
  • 'points d'axes' : points à partir du coin inférieur gauche des axes
  • 'pixels d'axes' : pixels à partir du coin inférieur gauche des axes
  • 'fraction d'axes' : (0, 0) est le coin inférieur gauche des axes et (1, 1) est le coin supérieur droit
  • 'points d'offset' : Spécifiez un décalage (en points) à partir de la valeur xy
  • 'pixels d'offset' : Spécifiez un décalage (en pixels) à partir de la valeur xy
  • 'data' : utiliser le système de coordonnées de données des axes

Remarque : pour les systèmes de coordonnées physiques (points ou pixels), l'origine est le (bas, gauche) de la figure ou des axes.

Facultativement, vous pouvez spécifier les propriétés de la flèche qui trace une flèche du texte au point annoté en donnant un dictionnaire de propriétés de flèche. Les clés valides sont :

  • width : la largeur de la flèche en points
  • frac : la fraction de la longueur de la flèche occupée par la tête
  • headwidth : la largeur de la base de la tête de flèche en points
  • shrink : déplacer l'extrémité et la base d'un certain pourcentage loin du point annoté et du texte
  • n'importe quelle clé pour matplotlib.patches.polygon (par exemple, facecolor)
import matplotlib.pyplot as plt
import numpy as np

from matplotlib.patches import Ellipse
from matplotlib.text import OffsetFrom

## Créez notre figure et les données que nous utiliserons pour tracer
fig, ax = plt.subplots(figsize=(4, 4))

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)

## Tracez une ligne et ajoutez quelques annotations simples
line, = ax.plot(t, s)
ax.annotate('pixels de figure',
            xy=(10, 10), xycoords='pixels de figure')
ax.annotate('points de figure',
            xy=(107, 110), xycoords='points de figure',
            fontsize=12)
ax.annotate('fraction de figure',
            xy=(.025,.975), xycoords='fraction de figure',
            horizontalalignment='left', verticalalignment='top',
            fontsize=20)

## Les exemples suivants montrent comment ces flèches sont dessinées.

ax.annotate('décalage de point à partir des données',
            xy=(3, 1), xycoords='data',
            xytext=(-10, 90), textcoords='points d'offset',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='center', verticalalignment='bottom')

ax.annotate('fraction d'axes',
            xy=(2, 1), xycoords='data',
            xytext=(0.36, 0.68), textcoords='fraction d'axes',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='right', verticalalignment='top')

## Vous pouvez également utiliser des points ou des pixels négatifs pour spécifier à partir de (droite, haut).
## Par exemple, (-10, 10) est 10 points à gauche du côté droit des axes et 10
## points au-dessus du bas

ax.annotate('décalage de pixel à partir de la fraction d'axes',
            xy=(1, 0), xycoords='fraction d'axes',
            xytext=(-20, 20), textcoords='pixels d'offset',
            horizontalalignment='right',
            verticalalignment='bottom')

ax.set(xlim=(-1, 5), ylim=(-3, 5))

Utilisation de multiples systèmes de coordonnées et de types d'axes

Vous pouvez spécifier le xypoint et le xytext dans des positions et des systèmes de coordonnées différents, et facultativement activer une ligne de connexion et marquer le point avec un marqueur. Les annotations fonctionnent également sur des axes polaires.

fig, ax = plt.subplots(subplot_kw=dict(projection='polar'), figsize=(3, 3))
r = np.arange(0, 1, 0.001)
theta = 2*2*np.pi*r
line, = ax.plot(theta, r)

ind = 800
thisr, thistheta = r[ind], theta[ind]
ax.plot([thistheta], [thisr], 'o')
ax.annotate('une annotation polaire',
            xy=(thistheta, thisr),  ## theta, rayon
            xytext=(0.05, 0.05),    ## fraction, fraction
            textcoords='fraction de figure',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='left',
            verticalalignment='bottom')

Personnalisation des styles de flèche et de bulle

La flèche entre xytext et le point d'annotation, ainsi que la bulle qui recouvre le texte d'annotation, sont hautement personnalisables. Voici quelques options de paramètres ainsi que leur résultat.

fig, ax = plt.subplots(figsize=(8, 5))

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = ax.plot(t, s, lw=3)

ax.annotate(
    'droite',
    xy=(0, 1), xycoords='data',
    xytext=(-50, 30), textcoords='points d\'offset',
    arrowprops=dict(arrowstyle="->"))
ax.annotate(
    'arc3,\nrad 0.2',
    xy=(0.5, -1), xycoords='data',
    xytext=(-80, -60), textcoords='points d\'offset',
    arrowprops=dict(arrowstyle="->",
                    connectionstyle="arc3,rad=.2"))
ax.annotate(
    'arc,\nangle 50',
    xy=(1., 1), xycoords='data',
    xytext=(-90, 50), textcoords='points d\'offset',
    arrowprops=dict(arrowstyle="->",
                    connectionstyle="arc,angleA=0,armA=50,rad=10"))
ax.annotate(
    'arc,\nbras',
    xy=(1.5, -1), xycoords='data',
    xytext=(-80, -60), textcoords='points d\'offset',
    arrowprops=dict(
        arrowstyle="->",
        connectionstyle="arc,angleA=0,armA=40,angleB=-90,armB=30,rad=7"))
ax.annotate(
    'angle,\nangle 90',
    xy=(2., 1), xycoords='data',
    xytext=(-70, 30), textcoords='points d\'offset',
    arrowprops=dict(arrowstyle="->",
                    connectionstyle="angle,angleA=0,angleB=90,rad=10"))
ax.annotate(
    'angle3,\nangle -90',
    xy=(2.5, -1), xycoords='data',
    xytext=(-80, -60), textcoords='points d\'offset',
    arrowprops=dict(arrowstyle="->",
                    connectionstyle="angle3,angleA=0,angleB=-90"))
ax.annotate(
    'angle,\narrondi',
    xy=(3., 1), xycoords='data',
    xytext=(-60, 30), textcoords='points d\'offset',
    bbox=dict(boxstyle="round", fc="0.8"),
    arrowprops=dict(arrowstyle="->",
                    connectionstyle="angle,angleA=0,angleB=90,rad=10"))
ax.annotate(
    'angle,\nround4',
    xy=(3.5, -1), xycoords='data',
    xytext=(-70, -80), textcoords='points d\'offset',
    size=20,
    bbox=dict(boxstyle="round4,pad=.5", fc="0.8"),
    arrowprops=dict(arrowstyle="->",
                    connectionstyle="angle,angleA=0,angleB=-90,rad=10"))
ax.annotate(
    'angle,\nrétrécissement',
    xy=(4., 1), xycoords='data',
    xytext=(-60, 30), textcoords='points d\'offset',
    bbox=dict(boxstyle="round", fc="0.8"),
    arrowprops=dict(arrowstyle="->",
                    shrinkA=0, shrinkB=10,
                    connectionstyle="angle,angleA=0,angleB=90,rad=10"))
## Vous pouvez passer une chaîne de caractères vide pour obtenir seulement les flèches d'annotation rendues
ax.annotate('', xy=(4., 1.), xycoords='data',
            xytext=(4.5, -1), textcoords='data',
            arrowprops=dict(arrowstyle="<->",
                            connectionstyle="bar",
                            ec="k",
                            shrinkA=5, shrinkB=5))

ax.set(xlim=(-1, 5), ylim=(-4, 3))

Plus d'exemples de systèmes de coordonnées

Voici quelques exemples supplémentaires de systèmes de coordonnées et de la manière dont la position des annotations peut être spécifiée.

fig, (ax1, ax2) = plt.subplots(1, 2)

bbox_args = dict(boxstyle="round", fc="0.8")
arrow_args = dict(arrowstyle="->")

## Ici, nous allons démontrer les limites du système de coordonnées et la manière dont
## nous plaçons le texte d'annotation.

ax1.annotate('fraction de figure : 0, 0', xy=(0, 0), xycoords='fraction de figure',
             xytext=(20, 20), textcoords='points d\'offset',
             ha="gauche", va="bas",
             bbox=bbox_args,
             arrowprops=arrow_args)

ax1.annotate('fraction de figure : 1, 1', xy=(1, 1), xycoords='fraction de figure',
             xytext=(-20, -20), textcoords='points d\'offset',
             ha="droite", va="haut",
             bbox=bbox_args,
             arrowprops=arrow_args)

ax1.annotate('fraction d\'axes : 0, 0', xy=(0, 0), xycoords='fraction d\'axes',
             xytext=(20, 20), textcoords='points d\'offset',
             ha="gauche", va="bas",
             bbox=bbox_args,
             arrowprops=arrow_args)

ax1.annotate('fraction d\'axes : 1, 1', xy=(1, 1), xycoords='fraction d\'axes',
             xytext=(-20, -20), textcoords='points d\'offset',
             ha="droite", va="haut",
             bbox=bbox_args,
             arrowprops=arrow_args)

## Il est également possible de générer des annotations déplaçables

an1 = ax1.annotate('Faites-moi glisser 1', xy=(.5,.7), xycoords='data',
                   ha="centre", va="centre",
                   bbox=bbox_args)

an2 = ax1.annotate('Faites-moi glisser 2', xy=(.5,.5), xycoords=an1,
                   xytext=(.5,.3), textcoords='fraction d\'axes',
                   ha="centre", va="centre",
                   bbox=bbox_args,
                   arrowprops=dict(patchB=an1.get_bbox_patch(),
                                   connectionstyle="arc3,rad=0.2",
                                   **arrow_args))
an1.draggable()
an2.draggable()

an3 = ax1.annotate('', xy=(.5,.5), xycoords=an2,
                   xytext=(.5,.5), textcoords=an1,
                   ha="centre", va="centre",
                   bbox=bbox_args,
                   arrowprops=dict(patchA=an1.get_bbox_patch(),
                                   patchB=an2.get_bbox_patch(),
                                   connectionstyle="arc3,rad=0.2",
                                   **arrow_args))

## Enfin, nous allons montrer quelques annotations et positions plus complexes

text = ax2.annotate('xy=(0, 1)\nxycoords=("data", "fraction d\'axes")',
                    xy=(0, 1), xycoords=("data", 'fraction d\'axes'),
                    xytext=(0, -20), textcoords='points d\'offset',
                    ha="centre", va="haut",
                    bbox=bbox_args,
                    arrowprops=arrow_args)

ax2.annotate('xy=(0.5, 0)\nxycoords=artist',
             xy=(0.5, 0.), xycoords=text,
             xytext=(0, -20), textcoords='points d\'offset',
             ha="centre", va="haut",
             bbox=bbox_args,
             arrowprops=arrow_args)

ax2.annotate('xy=(0.8, 0.5)\nxycoords=ax1.transData',
             xy=(0.8, 0.5), xycoords=ax1.transData,
             xytext=(10, 10),
             textcoords=OffsetFrom(ax2.bbox, (0, 0), "points"),
             ha="gauche", va="bas",
             bbox=bbox_args,
             arrowprops=arrow_args)

ax2.set(xlim=[-2, 2], ylim=[-2, 2])

Récapitulatif

Ce laboratoire a abordé les bases de l'annotation de graphes dans Matplotlib. Vous avez appris à spécifier les points d'annotation et de texte, à utiliser plusieurs systèmes de coordonnées et de types d'axes, à personnaliser les styles de flèches et de bulles, et de plus nombreux exemples de systèmes de coordonnées. Ces outils sont essentiels pour rendre les graphes plus visuellement attrayants et pour communiquer efficacement des informations.