0% ont trouvé ce document utile (0 vote)
3 vues260 pages

Guide Pratique Matplotlib

guide pratique sur Matplotlib avec Python

Transféré par

abdel fedala
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
3 vues260 pages

Guide Pratique Matplotlib

guide pratique sur Matplotlib avec Python

Transféré par

abdel fedala
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Formateur En Applications Informatiques

Édition
2026
Formateur En Applications Informatiques

Patrice REY
4435-199 RIO TINTO
PORTUGAL
© 2026 Patrice REY

email ʇ patricerey33@[Link]
site web ʇ [Link]
Amazon auteur ʇ [Link]/3fXLGqa
Linkedin auteur ʇ [Link]/3fe5YhD
Cours personnalisé ʇ reypatrice@[Link]
(C# - WPF - Python - Java - EXCEL)
Table des matières

Toutes les ressources complémentaires associées à ce livre


pourront être téléchargées gratuitement en allant
sur la fiche de cet ouvrage à l’adresse web [Link]

F01 - La fonction plot() ........................................................................................ 5


F02 - Les fonctions bar() et barh() ....................................................................... 13
F03 - La fonction scatter() ................................................................................... 21
F04 - La fonction pie() ......................................................................................... 29
F05 - La fonction hist() ......................................................................................... 39
F06 - Habiller un graphique ................................................................................. 49
F07 - Positionner plusieurs graphiques avec la fonction subplot() ........................ 59
F08 - Intégrer des tableaux avec la fonction table() ............................................... 69
F09 - Annoter un graphique avec la fonction text() ............................................... 79
F10 - A icher des images et des tableaux 2D avec la fonction imshow() ................ 91
F11 - Lister toutes les fonctions intégrées de Matplotlib ....................................... 101
F12 - Visualiser les couleurs prédéfinies de Matplotlib ......................................... 115
F13 - Visualiser les palettes de couleurs prédéfinies de Matplotlib ....................... 131
F14 - Exemples pratiques avec Matplotlib ........................................................... 147
La fonction plot() F01
Matplotlib est la bibliothèque de référence pour la visualisation de données en Python. Au
cœur de cette bibliothèque se trouve la fonction plot(), accessible via le module matplotlib.
pyplot (généralement importé sous l’alias plt). Cette fonction permet de tracer des courbes à
partir de données numériques, en reliant des points par des segments de droite.
Malgré son nom simple, plot() est une fonction particulièrement riche : elle accepte une grande
variété de paramètres qui permettent de contrôler l’apparence des courbes (couleur, style
de ligne, marqueurs, etc). C’est souvent la première fonction qu’un utilisateur de Matplotlib
apprend, et elle constitue la base de nombreuses visualisations plus complexes.

Importation des bibliothèques

Avant toute utilisation, il faut importer les modules nécessaires en utilisant les instructions
suivantes (le module pyplot est importé sous l’alias plt).

import [Link] as plt


import numpy as np
6 La fonction plot()

Syntaxe générale

La signature simplifiée de la fonction plot() est la suivante : [Link]([x], [y], [fmt], **kwargs). Les
paramètres principaux sont :
• x : séquence de valeurs pour l’axe des abscisses (optionnel).
• y : séquence de valeurs pour l’axe des ordonnées (obligatoire).
• fmt : chaîne de format abrégée combinant couleur, style de ligne et marqueur (optionnel).
• **kwargs : arguments nommés supplémentaires pour un contrôle fin de l’apparence.
Remarque : Si x est omis, Matplotlib utilise automatiquement les indices de y (c’est-à-dire 0,
1, 2, ..., n-1) comme abscisses.

Premier exemple

Commençons par un tracé minimal pour illustrer le fonctionnement de base.

import [Link] as plt


x = [1, 2, 3, 4, 5
y = [1, 4, 9, 16, 25
[Link](x, y)
[Link]()

Ce code trace la fonction y = x2 sur cinq points. L’appel à [Link]() est indispensable dans un
script Python pour a icher la fenêtre graphique. Dans un notebook Jupyter, l’a ichage se fait
automatiquement à la fin de la cellule.

La chaîne de format (fmt)

La chaîne de format fmt est un raccourci pratique combinant trois éléments : couleur, style de
ligne et marqueur. Sa syntaxe générale est fmt = ‘[marker][line][color]’.

Principales couleurs

Code Couleur

‘b’ bleu (blue)

‘g’ vert (green)


La fonction plot() 7

‘r’ rouge (red)

‘c’ cyan

‘m’ magenta

‘y’ jaune (yellow)

‘k’ noir (black)

‘w’ blanc (white)

Principaux styles de ligne

Code Style

‘-’ ligne continue (par défaut)

‘--’ ligne en tirets

‘-.’ ligne tiret-point

‘:’ ligne en pointillés

Principaux marqueurs

Code Marqueur

‘.’ point

‘o’ cercle

‘s’ carré (square)

‘^’ triangle vers le haut

‘v’ triangle vers le bas

‘*’ étoile

‘+’ plus
8 La fonction plot()

‘x’ croix

‘D’ losange (diamond)

Exemple combinant les trois

[Link](x, y, ‘ro--’) # cercles rouges reliés par des tirets


[Link](x, y, ‘g^:’) # triangles verts reliés par des pointillés
[Link](x, y, ‘k.-’) # points noirs reliés par une ligne continue

Paramètres nommés (kwargs)

Pour un contrôle plus fin, on utilise des arguments nommés. Ils o rent plus de lisibilité et
permettent d’accéder à l’ensemble des options disponibles. Les plus utilisés :
• color ou c : couleur (nom, code hexadécimal, tuple RGB, etc.).
• linestyle ou ls : style de ligne (‘-’, ‘--’, etc.).
• linewidth ou lw : épaisseur du trait (valeur numérique).
• marker : type de marqueur.
• markersize ou ms : taille des marqueurs.
• markerfacecolor ou mfc : couleur de remplissage des marqueurs.
• markeredgecolor ou mec : couleur du bord des marqueurs.
• label : libellé a iché dans la légende.
• alpha : transparence entre 0 (invisible) et 1 (opaque).

Exemple détaillé

import numpy as np
import [Link] as plt
x = [Link](0, 2 * [Link], 50
y = [Link](x)
[Link](x, y,
color=’purple’,
linestyle=’--’,
linewidth=2,
marker=’o’,
markersize=6,
markerfacecolor=’yellow’,
La fonction plot() 9
markeredgecolor=’black’,
label=’sin(x)’,
alpha=0.8
[Link](‘x’)
[Link](‘sin(x)’)
[Link](‘Fonction sinus’)
[Link]()
[Link](True)
[Link]()

Tracer plusieurs courbes

Il existe deux approches pour a icher plusieurs courbes sur le même graphique.

Appels successifs à plot()


C’est la méthode la plus lisible.

x = [Link](0, 2 * [Link], 100


[Link](x, [Link](x), ‘b-’, label=’sin(x)’)
[Link](x, [Link](x), ‘r--’, label=’cos(x)’)
[Link](x, [Link](x) * [Link](x), ‘g:’, label=’sin(x)·cos(x)’)
[Link]()
[Link]()

Plusieurs paires (x, y) dans un seul appel


On peut passer plusieurs couples de données et leur chaîne de format dans un même appel.

[Link](x, [Link](x), ‘b-’, x, [Link](x), ‘r--’)


[Link]()

Cette forme est concise mais devient vite illisible. On lui préfère généralement la première
approche.

Cas d’usage courants

Tracer une fonction mathématique


10 La fonction plot()

x = [Link](-5, 5, 200
y = x**2  2*x + 1
[Link](x, y, ‘b-’, linewidth=2
[Link](0, color=’gray’, linestyle=’:’)
[Link](0, color=’gray’, linestyle=’:’)
[Link](‘y = x²  2x + 1’)
[Link](True)
[Link]()

Série de données discrètes


Pour des mesures ponctuelles, on a iche souvent uniquement les marqueurs, sans ligne.

mois = [‘Jan’, ‘Fév’, ‘Mar’, ‘Avr’, ‘Mai’, ‘Jun’]


ventes = [120, 145, 130, 180, 210, 195
[Link](mois, ventes, ‘o’, markersize=10, color=’teal’)
[Link](‘Ventes mensuelles’)
[Link](‘Unités vendues’)
[Link]()

Comparaison de plusieurs séries


annees = [Link](2015, 2026
produit_a = [50, 55, 60, 58, 65, 70, 75, 80, 82, 88, 95
produit_b = [30, 40, 45, 55, 60, 62, 70, 78, 85, 92, 100
[Link](annees, produit_a, ‘o-’, label=’Produit A’)
[Link](annees, produit_b, ‘s--’, label=’Produit B’)
# personnaliser les étiquettes des axes
[Link](‘Année’)
[Link](‘Ventes (k€)’)
# personnaliser le titre et la légende
[Link](‘Évolution des ventes’)
[Link]()
[Link](True, alpha=0.3
[Link]()
La fonction plot() 11

Bonnes pratiques

• Toujours étiqueter les axes avec [Link]() et [Link]() : un graphique sans étiquettes
est di icilement interprétable.
• Utiliser label= et [Link]() dès qu’il y a plusieurs courbes, plutôt que d’expliquer les
couleurs dans le texte.
• Préférer les arguments nommés aux chaînes de format pour les graphiques destinés à
être lus par d’autres : color=’red’, linestyle=’--’ est plus explicite que ‘r--’.
• Utiliser [Link]() pour générer les abscisses de fonctions continues : cela donne un
tracé lisse avec peu d’e ort.
• Appeler [Link]() en début de script pour contrôler la taille : [Link](figsize=(10, 6)).
• Sauvegarder avec [Link](‘[Link]’, dpi=300) avant [Link](), sinon la figure peut
être e acée.

Conclusion

La fonction plot() est l’outil fondamental de Matplotlib pour visualiser des données. Sa force
réside dans sa double accessibilité : on peut l’utiliser en une ligne pour un tracé rapide, ou
exploiter ses nombreux paramètres pour produire des graphiques de qualité publication.
Pour aller plus loin, Matplotlib propose d’autres fonctions spécialisées : scatter() pour les
nuages de points, bar() pour les diagrammes en barres, hist() pour les histogrammes, ou
encore subplot() pour organiser plusieurs graphiques dans une même figure. La maîtrise de
plot() constitue néanmoins un socle solide pour aborder l’ensemble de la bibliothèque.
Les fonctions bar() et barh() F02
Les diagrammes en barres sont parmi les représentations graphiques les plus utilisées pour
visualiser des données catégorielles ou comparer des valeurs discrètes. Matplotlib propose
deux fonctions complémentaires pour les produire : bar() pour des barres verticales et barh()
pour des barres horizontales (le h signifiant horizontal).
Le choix entre les deux orientations n’est pas purement esthétique : les barres horizontales
sont particulièrement adaptées lorsque les étiquettes des catégories sont longues, ou
lorsqu’on compare un grand nombre de catégories (les étiquettes restent lisibles empilées
verticalement). Les barres verticales, plus traditionnelles, conviennent aux séries temporelles
et aux comparaisons avec peu de catégories.

Importation des bibliothèques

import [Link] as plt


import numpy as np
14 Les fonctions bar() et barh()

Syntaxe générale

La fonction bar() a comme signature [Link](x, height, width=0.8, bottom=None, **kwargs). Les
paramètres principaux sont :
• x : positions des barres sur l’axe horizontal (catégories ou valeurs numériques).
• height : hauteurs des barres (valeurs à représenter).
• width : largeur des barres (par défaut 0.8).
• bottom : base des barres (utile pour les barres empilées).
La fonction barh() a comme signature [Link](y, width, height=0.8, left=None, **kwargs). Les
paramètres sont analogues mais avec des axes inversés :
• y : positions des barres sur l’axe vertical.
• width : longueurs des barres (valeurs à représenter).
• height : épaisseur des barres (par défaut 0.8).
• left : base gauche des barres (pour les barres empilées).
Attention : la nomenclature peut surprendre. Dans barh(), width désigne la longueur de la
barre (donc la valeur représentée), tandis que height désigne son épaisseur. Ce n’est pas
intuitif mais cohérent avec l’orientation du graphique.

Premiers exemples

Barres verticales avec bar()


import [Link] as plt
categories = [‘Pommes’, ‘Bananes’, ‘Cerises’, ‘Dattes’]
quantites = [25, 40, 30, 15
[Link](categories, quantites)
[Link](‘Fruits’)
[Link](‘Quantité’)
[Link](‘Stock de fruits’)
[Link]()

Barres horizontales avec barh()


categories = [‘Pommes’, ‘Bananes’, ‘Cerises’, ‘Dattes’]
quantites = [25, 40, 30, 15
[Link](categories, quantites)
[Link](‘Quantité’)
[Link](‘Fruits’)
Les fonctions bar() et barh() 15
[Link](‘Stock de fruits’)
[Link]()

Astuce : avec barh(), les catégories sont a ichées du bas vers le haut. Pour obtenir un ordre
décroissant visuellement (la plus grande valeur en haut), on inverse l’axe par [Link]().invert_
yaxis().

Personnalisation des barres

Les principaux arguments nommés pour contrôler l’apparence des barres sont :

Argument Description

color Couleur de remplissage (une couleur ou une liste de couleurs)

edgecolor Couleur du contour des barres

linewidth Épaisseur du contour

alpha Transparence entre 0 et 1

hatch Motif de remplissage (‘/’, ‘\\’, ‘x’, ‘.’, ‘o’, etc.)

label Libellé a iché dans la légende

align Alignement des barres par rapport aux positions (‘center’ ou ‘edge’)

Exemple personnalisé

categories = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’]


valeurs = [23, 45, 56, 78, 32
[Link](categories, valeurs,
color=’steelblue’,
edgecolor=’black’,
linewidth=1.5,
16 Les fonctions bar() et barh()

alpha=0.8,
width=0.6
[Link](‘Diagramme personnalise’)
[Link]()

Couleurs individuelles par barre


On peut passer une liste de couleurs pour attribuer une teinte di érente à chaque barre.

categories = [‘Lun’, ‘Mar’, ‘Mer’, ‘Jeu’, ‘Ven’]


ventes = [120, 95, 140, 110, 180
couleurs = [‘#3498db’, ‘#e74c3c’, ‘#2ecc71’, ‘#f39c12’, ‘#9b59b6’]
[Link](categories, ventes, color=couleurs)
# personnalisation
[Link](‘Ventes de la semaine’)
[Link](‘Unites’)
[Link]()

Barres groupées
Pour comparer plusieurs séries côte à côte, on décale manuellement les positions des
barres. La technique consiste à générer un tableau de positions avec [Link](), puis à tracer
chaque série en appliquant un décalage égal à la largeur des barres.

import numpy as np
import [Link] as plt
categories = [‘Q1’, ‘Q2’, ‘Q3’, ‘Q4’]
produit_a = [20, 35, 30, 35
produit_b = [25, 32, 34, 20
positions = [Link](len(categories))
largeur = 0.35
[Link](positions - largeur/2, produit_a, largeur, label=’Produit A’)
[Link](positions + largeur/2, produit_b, largeur, label=’Produit B’)
[Link](positions, categories)
[Link](‘Trimestre’)
[Link](‘Ventes’)
[Link](‘Comparaison trimestrielle’)
[Link]()
[Link]()
Les fonctions bar() et barh() 17

Principe : chaque série est décalée de largeur/2 par rapport au centre. La fonction [Link]()
permet ensuite de remplacer les positions numériques par les noms des catégories.

Barres empilées

Pour empiler plusieurs séries sur une même barre, on utilise le paramètre bottom qui indique
la base de chaque barre. La deuxième série démarre au sommet de la première.

categories = [‘Lun’, ‘Mar’, ‘Mer’, ‘Jeu’, ‘Ven’]


matin = [10, 15, 12, 18, 20
apres_midi = [8, 12, 14, 10, 15
[Link](categories, matin, label=’Matin’, color=’skyblue’)
[Link](categories, apres_midi, bottom=matin, label=’Apres-midi’, color=’salmon’)
[Link](‘Nombre de clients’)
[Link](‘Frequentation journaliere’)
[Link]()
[Link]()

Pour plus de deux séries, on additionne les séries précédentes avec Numpy.

serie_1  [Link]([10, 15, 12, 18, 20


serie_2  [Link]([8, 12, 14, 10, 15
serie_3  [Link]([5, 8, 6, 9, 11
[Link](categories, serie_1, label=’Serie 1’)
[Link](categories, serie_2, bottom=serie_1, label=’Serie 2’)
[Link](categories, serie_3, bottom=serie_1  serie_2, label=’Serie 3’)
[Link]()
[Link]()

Annoter les barres

A icher la valeur au sommet de chaque barre améliore la lisibilité. Matplotlib fournit pour
cela la méthode bar_label().

categories = [‘A’, ‘B’, ‘C’, ‘D’]


valeurs = [23, 45, 56, 78
barres = [Link](categories, valeurs, color=’teal’)
18 Les fonctions bar() et barh()

plt.bar_label(barres, padding=3
[Link](‘Valeurs affichees’)
[Link]()

La méthode bar_label() accepte plusieurs paramètres utiles :


• padding : espace entre la barre et l’étiquette.
• fmt : format d’a ichage, par exemple ‘%.2f’ pour deux décimales.
• labels : liste personnalisée d’étiquettes.
• label_type : ‘edge’ (par défaut) ou ‘center’ pour placer les étiquettes au centre des barres.

Cas d’usage courants

Classement (barh() avec tri)

La fonction barh() brille pour les classements avec étiquettes longues.

pays = [‘France’, ‘Allemagne’, ‘Italie’, ‘Espagne’, ‘Pologne’]


population = [67.8, 83.2, 59.1, 47.4, 37.7
# Tri decroissant
indices = [Link](population)
pays_tries = [pays[i] for i in indices]
population_triee = [population[i] for i in indices]
[Link](pays_tries, population_triee, color=’darkgreen’)
[Link](‘Population (millions)’)
[Link](‘Population de quelques pays europeens’)
[Link]()

Valeurs négatives

Les barres supportent naturellement les valeurs négatives. On peut colorer di éremment les
barres positives et négatives.

categories = [‘Jan’, ‘Fev’, ‘Mar’, ‘Avr’, ‘Mai’, ‘Jun’]


variations = [5, 3, 8, 2, 6, 4
couleurs = [‘green’ if v >= 0 else ‘red’ for v in variations]
[Link](categories, variations, color=couleurs)
# personnalisation
[Link](0, color=’black’, linewidth=0.8
[Link](‘Variation (%’
Les fonctions bar() et barh() 19
[Link](‘Variations mensuelles’)
[Link]()

Histogramme de fréquences

Bien que [Link]() soit dédié aux histogrammes, bar() permet de tracer un diagramme de
fréquences à partir de données déjà comptées.

notes = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’]


effectifs = [12, 25, 18, 8, 3
[Link](notes, effectifs, color=’cornflowerblue’, edgecolor=’navy’)
# personnalisation
[Link](‘Note obtenue’)
[Link](‘Nombre d\’etudiants’)
[Link](‘Repartition des notes’)
[Link]()

Bonnes pratiques

• Choisir l’orientation en fonction des étiquettes : utiliser barh() dès que les noms de
catégories sont longs ou nombreux.
• Trier les données pour les classements : un diagramme trié (croissant ou décroissant) est
beaucoup plus lisible qu’un ordre alphabétique arbitraire.
• Éviter les graphiques 3D et les e ets décoratifs : ils déforment la perception des valeurs
sans rien apporter.
• Commencer l’axe des valeurs à zéro : tronquer l’axe rend les di érences visuellement
trompeuses. C’est une règle fondamentale des diagrammes en barres.
• Utiliser bar_label() quand la précision des valeurs compte, surtout si les barres sont
proches.
• Préférer des couleurs sobres : une seule couleur pour une série simple. Réserver les
couleurs multiples à des catégories qualitativement distinctes.
• Pour les barres groupées, limiter à 3 ou 4 séries : au-delà, la lecture devient di icile.
Envisager alors des sous-graphiques séparés.

Conclusion

Les fonctions bar() et barh() sont les outils fondamentaux de Matplotlib pour la représentation
de données catégorielles. Leur API est très proche : le passage de l’une à l’autre se fait
20 Les fonctions bar() et barh()

en échangeant les rôles des axes, ce qui permet d’adapter rapidement l’orientation aux
contraintes de lisibilité.
Combinées aux paramètres bottom (ou left pour barh()) et à des décalages manuels, elles
permettent également de produire des graphiques plus élaborés (barres empilées, barres
groupées) sans recourir à des bibliothèques tierces. Pour des besoins plus spécifiques, on
pourra se tourner vers stackplot() pour les empilements continus, ou vers des bibliothèques
comme Seaborn qui o rent des raccourcis pour les diagrammes en barres statistiques.
La fonction scatter() F03
La fonction scatter() de Matplotlib permet de tracer des nuages de points (scatter plots), c’est-
à-dire une représentation où chaque point du graphique correspond à un couple de valeurs (x,
y). Contrairement à plot() qui relie les points par des segments, scatter() a iche uniquement
les points, ce qui la rend particulièrement adaptée à l’exploration de données.
Son principal intérêt réside dans sa capacité à encoder jusqu’à quatre dimensions
simultanément sur un graphique 2D : deux dimensions pour la position (axes x et y), une
troisième pour la taille des points, et une quatrième pour leur couleur. Cela en fait un outil
privilégié pour visualiser des corrélations, détecter des regroupements (clusters) ou mettre en
évidence des valeurs atypiques.

Importation des bibliothèques

import [Link] as plt


import numpy as np
22 La fonction scatter()

Syntaxe générale

La signature simplifiée de la fonction est [Link](x, y, s=None, c=None, marker=None,


cmap=None, alpha=None, **kwargs). Les paramètres principaux sont :
• x : séquence de valeurs pour l’axe des abscisses.
• y : séquence de valeurs pour l’axe des ordonnées.
• s : taille des points (size), scalaire ou séquence.
• c : couleur des points, scalaire, séquence ou tableau de valeurs.
• marker : forme des points (‘o’, ‘s’, ‘^’, etc.).
• cmap : carte de couleurs utilisée quand c est une séquence numérique.
• alpha : transparence entre 0 et 1.
Di érence avec plot() : dans plot(x, y, ‘o’), tous les points ont la même taille et la même couleur,
fixées globalement. Avec scatter(), s et c peuvent être des tableaux de même longueur que x et
y, permettant un encodage individuel pour chaque point.

Premier exemple

Un nuage de points minimaliste.

import [Link] as plt


import numpy as np
[Link](42)
x = [Link](50)
y = [Link](50)
[Link](x, y)
[Link](‘x’)
[Link](‘y’)
[Link](‘Nuage de points aleatoire’)
[Link]()

L’appel à [Link](42) fixe la graine du générateur aléatoire : cela garantit que le même
code produit toujours le même résultat, ce qui est utile pour reproduire un exemple.

Contrôler la taille des points

Le paramètre s contrôle la taille des points (unité : points au carré). Sa valeur par défaut est
36.
La fonction scatter() 23

Taille uniforme

[Link](x, y, s=100 # tous les points de taille 100


[Link](x, y, s=20 # tous petits
[Link](x, y, s=200 # tous grands

Taille variable

Quand s est un tableau de même longueur que x, chaque point reçoit sa propre taille. On
encode ainsi une troisième variable.

[Link](0)
x = [Link](30)
y = [Link](30)
tailles = [Link](20, 400, size=30
[Link](x, y, s=tailles, alpha=0.6
[Link](‘Taille variable’)
[Link]()

Astuce : pour que la taille soit proportionnelle à une variable métier (population, chi re
d’a aires, etc), on multiplie par un facteur d’échelle pour rester dans une plage visuellement
lisible.

population = [Link]([1.2, 3.5, 8.0, 2.1, 5.6


[Link](x, y, s=population * 50

Contrôler la couleur des points

Le paramètre c est très flexible et accepte plusieurs types de valeurs.

Couleur uniforme

[Link](x, y, c=’red’)
[Link](x, y, c=’#2E86AB’)
[Link](x, y, c=’steelblue’)

Couleur catégorielle
24 La fonction scatter()

Pour colorer les points par groupe, on passe une liste de couleurs (une par point).

groupes = [‘A’, ‘B’, ‘A’, ‘C’, ‘B’, ‘A’, ‘C’, ‘B’]


x = [Link](8)
y = [Link](8)
palette = {‘A’: ‘red’, ‘B’: ‘blue’, ‘C’: ‘green’}
couleurs = [palette[g] for g in groupes]
[Link](x, y, c=couleurs, s=100
[Link]()

Couleur selon une variable numérique (cmap)

C’est l’utilisation la plus puissante : quand c est un tableau de nombres, Matplotlib les
convertit en couleurs via une carte de couleurs (colormap) définie par cmap.

[Link](1)
x = [Link](100)
y = [Link](100)
valeurs = [Link](100)
[Link](x, y, c=valeurs, cmap=’viridis’, s=80
[Link](label=’Intensite’)
[Link](‘Nuage colore selon une variable’)
[Link]()

L’appel à [Link]() ajoute une échelle de couleurs à droite du graphique, indispensable


pour que le lecteur puisse interpréter les teintes.

Principales cartes de couleurs

Famille Exemples et usage

‘viridis’, ‘plasma’, ‘inferno’, ‘magma’


Séquentielles
valeurs ordonnées du bas vers le haut

‘coolwarm’, ‘RdBu’, ‘seismic’


Divergentes
valeurs centrées autour d’une référence (ex. zéro)

‘tab10’, ‘Set1’, ‘Paired’


Qualitatives
catégories distinctes sans ordre
La fonction scatter() 25

‘jet’, ‘rainbow’
Classiques
à éviter : perception non uniforme

Recommandation : privilégier ‘viridis’ (carte par défaut depuis Matplotlib 2.0) pour les données
continues : elle est lisible en noir et blanc, accessible aux daltoniens, et perçue de façon
uniforme par l’œil humain.

Formes des points (marker)

Le paramètre marker permet de choisir la forme des points. Les principales formes disponibles
dans Matplotlib sont :

Code Forme
‘o’ cercle (par défaut)
‘s’ carré
‘^’ triangle vers le haut
‘v’ triangle vers le bas
‘D’ losange
‘*’ étoile
‘+’ plus
‘x’ croix
‘p’ pentagone
‘h’ hexagone

Limitation : contrairement à c et s, marker n’accepte pas une liste de formes dans un seul
appel. Pour a icher plusieurs formes, il faut faire un appel à scatter() par catégorie.

Contour des points

Deux paramètres contrôlent le contour :


• edgecolors : couleur du contour (par exemple ‘black’).
• linewidths : épaisseur du contour.
26 La fonction scatter()

[Link](x, y,
s=150,
c=’skyblue’,
edgecolors=’navy’,
linewidths=1.5

Un contour noir fin rend les points plus nets, surtout quand ils se chevauchent ou sur fond
clair.

Cas d’usage courants

Corrélation entre deux variables

C’est l’usage canonique du nuage de points : visualiser la relation entre deux grandeurs
numériques.

[Link](2)
taille = [Link](170, 10, 100
poids = 0.8 * taille - 70  [Link](0, 5, 100
[Link](taille, poids, alpha=0.6, edgecolors=’black’)
[Link](‘Taille (cm)’)
[Link](‘Poids (kg)’)
[Link](‘Correlation taille / poids’)
[Link](True, alpha=0.3
[Link]()

Graphique à bulles (4 dimensions)

On exploite simultanément la position, la taille et la couleur pour encoder quatre variables.

[Link](3)
pib = [Link](5, 50, 20 # axe x
esperance_vie = [Link](60, 85, 20 # axe y
population = [Link](1, 100, 20 # taille
continent = [Link](20) # couleur
[Link](pib, esperance_vie,
s=population * 10,
c=continent,
La fonction scatter() 27
cmap=’tab10’,
alpha=0.7,
edgecolors=’black’)
[Link](‘PIB par habitant (k$)’)
[Link](‘Esperance de vie (annees)’)
[Link](‘Graphique a bulles’)
[Link](label=’Continent’)
[Link]()

Nuage de points par catégorie

Pour a icher plusieurs groupes avec une légende, on fait un appel par catégorie.

[Link](4)
groupe_a_x = [Link](2, 0.5, 30
groupe_a_y = [Link](3, 0.5, 30
groupe_b_x = [Link](4, 0.5, 30
groupe_b_y = [Link](5, 0.5, 30
groupe_c_x = [Link](6, 0.5, 30
groupe_c_y = [Link](2, 0.5, 30
[Link](groupe_a_x, groupe_a_y, c=’red’, marker=’o’, label=’Groupe A’)
[Link](groupe_b_x, groupe_b_y, c=’blue’, marker=’s’, label=’Groupe B’)
[Link](groupe_c_x, groupe_c_y, c=’green’, marker=’^’, label=’Groupe C’)
[Link]()
[Link](‘Classification en 3 groupes’)
[Link]()

Superposition avec une courbe de tendance

On combine scatter() et plot() pour ajouter une régression linéaire aux données.

[Link](5)
x = [Link](0, 10, 50
y = 2 * x + 1  [Link](0, 2, 50
# Regression lineaire
coefficients = [Link](x, y, 1
droite = np.poly1d(coefficients)
[Link](x, y, alpha=0.6, label=’Donnees’)
28 La fonction scatter()

[Link](x, droite(x), ‘r-’, linewidth=2, label=’Regression’)


[Link](‘x’)
[Link](‘y’)
[Link]()
[Link]()

Bonnes pratiques

• Utiliser alpha quand les points se chevauchent : une transparence de 0.5 à 0.7 permet de
visualiser la densité là où les points s’accumulent.
• Ajouter un contour avec edgecolors=’black’ améliore la lisibilité, en particulier pour les
points clairs ou nombreux.
• Toujours accompagner cmap d’une colorbar() : une couleur sans échelle est ininterprétable.
• Privilégier ‘viridis’ ou ‘plasma’ pour les données continues et éviter ‘jet’ et ‘rainbow’ qui
déforment la perception.
• Choisir plot(x, y, ‘o’) plutôt que scatter() quand tous les points ont la même taille et la
même couleur : c’est plus rapide à tracer pour de grands jeux de données.
• Pour des nuages très denses (plusieurs milliers de points), envisager [Link]() ou plt.
hist2d() qui a ichent la densité plutôt que les points individuels.
• Étiqueter les axes avec leur unité : un nuage de points sans contexte est peu informatif.

Conclusion

La fonction scatter() est l’un des outils les plus expressifs de Matplotlib. En exploitant position,
taille, couleur et forme, elle permet de visualiser simultanément plusieurs dimensions d’un
jeu de données sur un seul graphique. C’est la fonction de choix pour explorer des données,
détecter des corrélations, identifier des regroupements ou repérer des valeurs aberrantes.
Au-delà de scatter(), l’écosystème Matplotlib o re des variantes spécialisées : hexbin() et
hist2d() pour les très grands nuages, errorbar() pour ajouter des barres d’erreur, ou encore
des bibliothèques comme Seaborn qui proposent des nuages de points statistiques avec
régression intégrée via regplot() ou pairplot().
La fonction pie() F04
La fonction pie() de Matplotlib permet de tracer des diagrammes circulaires, appelés aussi
camemberts (pie charts). Ce type de graphique représente la décomposition d’un tout en
plusieurs parts, chaque part étant un secteur angulaire dont la surface est proportionnelle
à la valeur qu’il représente. Les diagrammes circulaires sont appropriés pour visualiser des
proportions (pourcentages, répartitions, parts de marché), à condition que :
• Les catégories forment un ensemble exhaustif (leur somme a un sens).
• Le nombre de catégories reste raisonnable (idéalement moins de 7).
• Les di érences de taille entre les parts sont su isamment marquées pour être
perceptibles visuellement.
Il est à noter que la communauté de la visualisation de données est souvent critique envers
les diagrammes circulaires. L’œil humain compare mal les angles, et un diagramme en barres
est fréquemment plus lisible. Il reste néanmoins utile pour les communications grand public.

Importation des bibliothèques

import [Link] as plt


import numpy as np
30 La fonction pie()

Syntaxe générale

La signature simplifiée de la fonction est [Link](x, labels=None, colors=None, autopct=None,


explode=None, shadow=False, startangle=0, counterclock=True, **kwargs). Les paramètres
principaux sont :
• x : séquence de valeurs à représenter (les tailles des secteurs).
• labels : libellés associés à chaque secteur.
• colors : liste des couleurs des secteurs.
• autopct : format d’a ichage des pourcentages sur les secteurs.
• explode : séquence contrôlant le décalage radial de chaque secteur.
• shadow : a iche une ombre portée sous le camembert.
• startangle : angle de départ (en degrés) du premier secteur.
• counterclock : sens de rotation (True = anti-horaire par défaut).
Normalisation automatique : si la somme des valeurs de x est supérieure à 1, Matplotlib
normalise automatiquement les valeurs pour qu’elles totalisent 100 %. Il est donc inutile de
convertir soi-même les données en pourcentages avant de les passer à pie().

Premier exemple

Un diagramme circulaire minimal.

import [Link] as plt


categories = [‘Pommes’, ‘Bananes’, ‘Cerises’, ‘Dattes’]
quantites = [40, 25, 20, 15
[Link](quantites, labels=categories)
[Link](‘Repartition des fruits’)
[Link]()

Par défaut, Matplotlib peut produire un diagramme légèrement elliptique si les axes n’ont pas
la même échelle. Pour garantir un cercle parfait, on ajoute [Link](‘equal’).
Alternative équivalente : utiliser l’argument autopct sur la figure, Matplotlib respecte
alors automatiquement le rapport d’aspect. En pratique, on prend l’habitude d’ajouter
systématiquement [Link](‘equal’).

Afficher les pourcentages

Le paramètre autopct permet d’a icher automatiquement la valeur (en pourcentage) sur
La fonction pie() 31
chaque secteur. Il accepte une chaîne de format de type printf() ou une fonction.

Format simple

[Link](quantites, labels=categories, autopct=’%1.1f%%’)


[Link](‘equal’)
[Link]()

Le format ‘%1.1f%%’ signifie :


• %1.1f : nombre à virgule flottante avec 1 chi re après la virgule.
• %% : le caractère % littéral (un seul % serait interprété comme un format).

Autres formats courants

Format Résultat

‘%.0f%%’ sans décimale : 40%

‘%.1f%%’ 1 décimale : 40.0%

‘%.2f%%’ 2 décimales : 40.00%

Format personnalisé via une fonction

Pour a icher à la fois le pourcentage et la valeur absolue, on passe une fonction à autopct.

# fonction
def formater_etiquette(pourcentage, valeurs_totales=quantites):
total = sum(valeurs_totales)
valeur_absolue = int(round(pourcentage * total / 100
return f’{pourcentage:.1f}%\n({valeur_absolue})’
# visualisation
[Link](quantites, labels=categories, autopct=formater_etiquette)
[Link](‘equal’)
[Link]()

La fonction reçoit automatiquement le pourcentage calculé par Matplotlib et doit retourner la


chaîne à a icher sur le secteur.
32 La fonction pie()

Personnalisation

Couleurs

Les couleurs sont passées sous forme de liste : couleurs = [‘#FF6B6B’, ‘#4ECDC4’, ‘#45B7D1’,
‘#FFA07A’].

[Link](quantites, labels=categories, colors=couleurs, autopct=’%1.1f%%’)


[Link](‘equal’)
[Link]()

On peut aussi utiliser une palette via une carte de couleurs.

couleurs = [Link].Pastel1([Link](len(categories)))
[Link](quantites, labels=categories, colors=couleurs, autopct=’%1.1f%%’)
[Link](‘equal’)
[Link]()

Angle de départ et sens de rotation

Par défaut, le premier secteur commence à l’angle 0 (à droite, équivalent à 3h sur une horloge)
et tourne dans le sens anti-horaire. Pour démarrer en haut (position 12h) et tourner dans le
sens horaire.

[Link](quantites,
labels=categories,
autopct=’%1.1f%%’,
startangle=90, # demarre en haut
counterclock=False) # sens horaire
[Link](‘equal’)
[Link]()

Convention : la disposition la plus lisible place le plus grand secteur en haut à droite et tourne
dans le sens horaire, car c’est le sens naturel de lecture. On trie donc généralement les
données par ordre décroissant.

Mettre en évidence un secteur (explode)

Le paramètre explode permet d’écarter un ou plusieurs secteurs du centre. Il prend une


La fonction pie() 33
séquence de même longueur que les données, où chaque valeur indique la distance de
décalage (en fraction du rayon).

ecartement = [0, 0.1, 0, 0 # on isole le 2e secteur (Bananes)


[Link](quantites,
labels=categories,
autopct=’%1.1f%%’,
explode=ecartement,
shadow=True)
[Link](‘equal’)
[Link]()

Personnalisation des bords

On passe un dictionnaire à wedgeprops pour contrôler l’apparence des secteurs (bord,


épaisseur, transparence).

[Link](quantites,
labels=categories,
autopct=’%1.1f%%’,
wedgeprops={‘edgecolor’: ‘white’, ‘linewidth’ 2
[Link](‘equal’)
[Link]()

Diagramme en anneau (donut)

Un diagramme en anneau (donut chart) est un camembert avec un trou au centre. Il se


construit en définissant la largeur des secteurs via wedgeprops.

[Link](quantites,
labels=categories,
autopct=’%1.1f%%’,
wedgeprops={‘width’ 0.4, ‘edgecolor’: ‘white’})
[Link](‘equal’)
[Link](‘Diagramme en anneau’)
[Link]()

La valeur de ‘width’ (entre 0 et 1) définit l’épaisseur de l’anneau en fraction du rayon. Une


34 La fonction pie()

valeur de 0.4 laisse un trou central de 60 % du rayon.


Astuce : on a iche souvent une valeur totale au centre du trou, ce qui est impossible dans un
camembert classique.

total = sum(quantites)
[Link](quantites, labels=categories, autopct=’%1.1f%%’,
wedgeprops={‘width’ 0.4, ‘edgecolor’: ‘white’})
[Link](0, 0, f’Total\n{total}’, ha=’center’, va=’center’, fontsize=16, fontweight=’bold’)
[Link](‘equal’)
[Link]()

Valeurs de retour

La fonction pie() retourne un tuple qui permet de manipuler finement les éléments graphiques
après la création.

secteurs, textes_labels, textes_pct =


[Link](
quantites,
labels=categories,
autopct=’%1.1f%%’
)

• secteurs : liste d’objets Wedge (les secteurs).


• textes_labels : liste des objets texte des libellés.
• textes_pct : liste des objets texte des pourcentages (seulement si autopct est défini).
Exemple de mise en forme des pourcentages en blanc et gras.

secteurs, textes_labels, textes_pct = [Link](


quantites,
labels=categories,
autopct=’%1.1f%%’,
colors=[‘#2E86AB’, ‘#A23B72’, ‘#F18F01’, ‘#C73E1D’])
for texte in textes_pct:
texte.set_color(‘white’)
texte.set_fontweight(‘bold’)
[Link](‘equal’)
La fonction pie() 35
[Link]()

Cas d’usage courants

Répartition budgétaire

postes = [‘Logement’, ‘Alimentation’, ‘Transport’, ‘Loisirs’, ‘Epargne’, ‘Autres’]


depenses = [800, 400, 200, 150, 300, 150
[Link](figsize=(8, 8
[Link](depenses,
labels=postes,
autopct=’%1.1f%%’,
startangle=90,
counterclock=False,
wedgeprops={‘edgecolor’: ‘white’, ‘linewidth’ 1.5
[Link](‘Repartition mensuelle du budget’, fontsize=14
[Link](‘equal’)
[Link]()

Tri préalable des données


Pour une lecture optimale, on trie les catégories par ordre décroissant avant de les a icher.
categories = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’]
valeurs = [15, 35, 10, 25, 15
# Tri decroissant via argsort
indices = [Link](valeurs)[::-1
categories_triees = [categories[i] for i in indices]
valeurs_triees = [valeurs[i] for i in indices]
[Link](valeurs_triees, labels=categories_triees, autopct=’%1.1f%%’, startangle=90, counterclock=False)
[Link](‘equal’)
[Link]()

Regrouper les petites parts


Quand une catégorie représente moins de quelques pourcents, il est souvent utile de la
regrouper dans une rubrique "Autres" pour éviter d’encombrer le graphique.

categories = [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’]


valeurs = [45, 25, 15, 8, 3, 2, 2
36 La fonction pie()

seuil = 5 # pourcent minimum


total = sum(valeurs)
grandes_cat = []
grandes_val = []
petites_val = 0
for cat, val in zip(categories, valeurs):
if val / total * 100  seuil:
grandes_cat.append(cat)
grandes_val.append(val)
else:
petites_val += val
if petites_val > 0
grandes_cat.append(‘Autres’)
grandes_val.append(petites_val)
# visualisation
[Link](grandes_val, labels=grandes_cat, autopct=’%1.1f%%’,
startangle=90, counterclock=False)
[Link](‘equal’)
[Link]()

Bonnes pratiques

• Limiter le nombre de secteurs : au-delà de 6 ou 7 catégories, la lisibilité se dégrade.


Regrouper les petites parts dans une rubrique "Autres".
• Trier les données par ordre décroissant et commencer en haut (startangle=90,
counterclock=False) pour suivre le sens de lecture naturel.
• Toujours appeler [Link](‘equal’) pour garantir un cercle et non une ellipse.
• A icher les pourcentages avec autopct : l’œil perçoit mal les angles, les valeurs chi rées
compensent cette faiblesse perceptive.
• Éviter les e ets 3D et les ombres marquées : ils déforment la perception des proportions.
Matplotlib ne propose pas nativement de camembert 3D et c’est voulu.
• Choisir des couleurs contrastées mais harmonieuses. Les palettes ‘Pastel1’, ‘Set2’ ou
‘tab10’ sont de bons points de départ.
• Envisager une alternative : pour comparer précisément des valeurs, un diagramme en
barres horizontales (barh()) est presque toujours plus lisible qu’un camembert.
• Utiliser un anneau plutôt qu’un camembert plein quand on veut a icher une valeur totale
ou un indicateur synthétique au centre.
La fonction pie() 37

Conclusion

La fonction pie() est un outil classique de la visualisation de données, bien adapté à la


représentation de proportions simples destinées à un large public. Ses nombreux paramètres
(autopct, explode, startangle, wedgeprops) permettent de produire rapidement des graphiques
de qualité professionnelle, y compris des variantes populaires comme le diagramme en
anneau.
Malgré ses critiques légitimes dans le monde de l’analyse de données, le camembert reste
incontournable dans la communication et le reporting. L’essentiel est de connaître ses limites
car un diagramme circulaire bien conçu (peu de parts, triées, annotées) peut être parfaitement
e icace, tandis qu’un camembert surchargé devient rapidement illisible. En cas de doute, un
simple barh() trié reste souvent le meilleur choix.
La fonction hist() F05
La fonction hist() de Matplotlib permet de tracer des histogrammes, un type de graphique
fondamental en statistique descriptive. Un histogramme représente la distribution d’une
variable numérique continue : les données sont regroupées en intervalles, appelés classes
(bins), et la hauteur de chaque barre correspond au nombre d’observations tombant dans
l’intervalle correspondant. Il ne faut pas confondre un histogramme avec un diagramme en
barres : le premier représente des e ectifs d’intervalles numériques continus (barres collées
les unes aux autres), tandis que le second représente des catégories discrètes (barres
séparées). Cette distinction est essentielle car les deux graphiques répondent à des questions
statistiques di érentes. L’histogramme est l’outil de choix pour :
• Visualiser la forme d’une distribution (symétrique, asymétrique, bimodale).
• Détecter des valeurs aberrantes (outliers).
• Comparer des données observées à une distribution théorique (normale, uniforme, etc).
• Repérer des seuils naturels ou des regroupements dans les données.

Importation des bibliothèques


import [Link] as plt
import numpy as np
40 La fonction hist()

Syntaxe générale

La signature simplifiée de la fonction est [Link](x, bins=10, range=None, density=False,


cumulative=False, histtype=’bar’, orientation=’vertical’, color=None, label=None, **kwargs). Les
paramètres principaux sont :
• x : séquence de valeurs numériques (les données à analyser).
• bins : nombre de classes, ou liste des bornes d’intervalles, ou méthode automatique.
• range : tuple (min, max) définissant la plage de valeurs prise en compte.
• density : si True, normalise en densité de probabilité (aire totale = 1).
• cumulative : si True, a iche l’histogramme cumulé.
• histtype : style d’histogramme (‘bar’, ‘step’, ‘stepfilled’).
• orientation : ‘vertical’ (défaut) ou ‘horizontal’.
• color : couleur de remplissage des barres.
Valeurs de retour : contrairement à beaucoup de fonctions de Matplotlib, hist() retourne un
tuple de trois éléments : (e ectifs, bornes, patches). On peut donc récupérer les valeurs
calculées pour les exploiter par la suite.

Premier exemple

Un histogramme minimal sur des données tirées d’une loi normale.

import [Link] as plt


import numpy as np
[Link](42)
donnees = [Link](loc=100, scale=15, size=1000
[Link](donnees)
# personnalisation
[Link](‘Valeur’)
[Link](‘Effectif’)
[Link](‘Distribution des donnees’)
# visualisation
[Link]()

Par défaut, hist() découpe les données en 10 intervalles de largeur uniforme. Les paramètres
loc et scale de [Link]() définissent respectivement la moyenne et l’écart-type de
la loi.
La fonction hist() 41

Choix du nombre de classes (bins)

Le choix du nombre de classes est crucial : trop peu de classes masquent les détails de la
distribution, trop de classes produisent un graphique bruité et irrégulier. C’est souvent le
paramètre sur lequel on ajuste le plus.

Nombre fixe

[Link](donnees, bins=5 # tres peu detaille


[Link](donnees, bins=30 # compromis frequent
[Link](donnees, bins=100 # tres detaille, souvent bruite

Bornes personnalisées

On peut passer une liste explicite des bornes d’intervalles. Les classes peuvent alors être de
largeurs di érentes.

bornes = [60, 80, 90, 100, 110, 120, 140


[Link](donnees, bins=bornes, edgecolor=’black’)
[Link]()

Méthodes automatiques

Matplotlib (via NumPy) propose plusieurs méthodes pour calculer automatiquement un


nombre de classes approprié.

Méthode Description

‘auto’ meilleur des méthodes ‘sturges’ et ‘fd’ (recommandé)

‘fd’ Freedman-Diaconis : robuste aux valeurs aberrantes

‘sturges’ formule classique, adaptée aux petits échantillons

‘scott’ adapté aux distributions normales

‘rice’ formule simple basée sur la taille de l’échantillon


42 La fonction hist()

‘sqrt’ racine carrée de la taille de l’échantillon

[Link](donnees, bins=’auto’, edgecolor=’black’)


[Link]()

Effectifs, fréquences et densité

Par défaut, l’axe vertical représente les e ectifs (nombre de valeurs dans chaque intervalle).
Le paramètre density permet de changer d’échelle.

EƯectifs (par défaut)

[Link](donnees, bins=30
[Link](‘Effectif’)

Densité de probabilité
Avec density=True, les barres sont normalisées de sorte que l’aire totale sous l’histogramme
soit égale à 1. Cela permet de comparer l’histogramme à une densité théorique.

[Link](donnees, bins=30, density=True, edgecolor=’black’, alpha=0.7


# Superposition de la densite theorique
abscisses = [Link]([Link](), [Link](), 200
moyenne = [Link]()
ecart_type = [Link]()
densite_theorique =
1 / (ecart_type * [Link](2 * [Link]))) * [Link](-0.5 * ((abscisses - moyenne) / ecart_type) ** 2
[Link](abscisses, densite_theorique, ‘r-’, linewidth=2, label=’Loi normale theorique’)
[Link]()
[Link](‘Valeur’)
[Link](‘Densite’)
[Link]()

Attention : avec density=True, les hauteurs ne sont pas des pourcentages. Ce sont des
densités, dont la valeur dépend de la largeur des classes. Pour obtenir des fréquences en
pourcentage, il faut calculer manuellement ou utiliser weights.
La fonction hist() 43

Fréquences en pourcentage

poids = np.ones_like(donnees) / len(donnees) * 100


[Link](donnees, bins=30, weights=poids, edgecolor=’black’)
[Link](‘Frequence (%’
[Link]()

Histogramme cumulé

Avec cumulative=True, chaque barre a iche le cumul des e ectifs (ou de la densité) depuis le
début. La dernière barre atteint donc le total (ou 1 si density=True).

[Link](donnees, bins=30,
cumulative=True,
density=True,
histtype=’step’,
linewidth=2
[Link](‘Frequence cumulee’)
[Link](‘Fonction de repartition empirique’)
[Link](True, alpha=0.3
[Link]()

Un histogramme cumulé avec density=True représente la fonction de répartition empirique,


très utile pour lire rapidement des quantiles (valeur correspondant à une fréquence cumulée
donnée).

Styles d’histogrammes (histtype)

Le paramètre histtype contrôle l’apparence générale de l’histogramme.

Valeur Rendu

‘bar’ barres pleines classiques (par défaut)

‘barstacked’ barres empilées (plusieurs séries)

‘step’ contour en escalier sans remplissage


44 La fonction hist()

‘stepfilled’ contour en escalier avec remplissage

[Link](donnees, bins=30, histtype=’step’, linewidth=2


[Link](donnees, bins=30, histtype=’stepfilled’, alpha=0.5

Les styles ‘step’ et ‘stepfilled’ sont particulièrement adaptés à la superposition de plusieurs


histogrammes, car ils laissent voir les distributions à travers les contours.

Comparer plusieurs distributions

Superposition avec transparence

[Link](0)
echantillon_a = [Link](100, 15, 1000
echantillon_b = [Link](110, 20, 1000
[Link](echantillon_a, bins=30, alpha=0.5, label=’Groupe A’, color=’blue’)
[Link](echantillon_b, bins=30, alpha=0.5, label=’Groupe B’, color=’red’)
[Link](‘Valeur’)
[Link](‘Effectif’)
[Link]()
[Link](‘Comparaison de deux distributions’)
[Link]()

Contours superposés
Pour une comparaison plus lisible, on utilise histtype=’step’.

[Link](echantillon_a, bins=30, histtype=’step’, linewidth=2, label=’Groupe A’)


[Link](echantillon_b, bins=30, histtype=’step’, linewidth=2, label=’Groupe B’)
[Link]()
[Link]()

Plusieurs séries dans un seul appel


On peut passer une liste de tableaux à hist() : Matplotlib a iche alors les barres côte à côte
par classe.

[Link]([echantillon_a, echantillon_b],
bins=20,
La fonction hist() 45
label=[‘Groupe A’, ‘Groupe B’],
color=[‘steelblue’, ‘salmon’])
[Link]()
[Link]()

Exploiter les valeurs de retour

Comme mentionné plus haut, hist() retourne un tuple de trois éléments : e ectifs, bornes,
rectangles = [Link](donnees, bins=20).
• e ectifs : tableau des e ectifs (ou densités) de chaque classe.
• bornes : tableau des bornes d’intervalles (longueur = nombre_de_classes + 1).
• rectangles : liste des objets graphiques (utiles pour les modifier individuellement).
Exemple : colorer en rouge la classe la plus peuplée (le mode).

effectifs, bornes, rectangles =


[Link](donnees, bins=20, color=’lightgray’, edgecolor=’black’)
indice_maximum = [Link](effectifs)
rectangles[indice_maximum].set_facecolor(‘red’)
[Link](‘Valeur’)
[Link](‘Effectif’)
[Link](‘Classe modale mise en evidence’)
[Link]()

Cas d’usage courants

Vérifier la normalité d’une distribution

[Link](7)
tailles = [Link](175, 8, 500
[Link](tailles, bins=’auto’, density=True, edgecolor=’black’, alpha=0.7, color=’skyblue’)
# Moyenne et ecart-type observes
moyenne = [Link]()
ecart_type = [Link]()
abscisses = [Link]([Link](), [Link](), 200
densite =
1 / (ecart_type * [Link](2 * [Link]))) * [Link](-0.5 * ((abscisses - moyenne) / ecart_type) ** 2
[Link](abscisses, densite, ‘r-’, linewidth=2, label=f’N({moyenne:.1f}, {ecart_type:.1f})’)
46 La fonction hist()

[Link](‘Taille (cm)’)
[Link](‘Densite’)
[Link]()
[Link]()

Détecter des valeurs aberrantes


Un histogramme révèle facilement des valeurs isolées (aberrantes), très éloignées du reste
de la distribution.

[Link](1)
donnees_normales = [Link](50, 10, 990
valeurs_aberrantes = [Link]([150, 160, 155, 148, 165, 170, 175, 168, 155, 160
donnees_completes = [Link]([donnees_normales, valeurs_aberrantes])
[Link](donnees_completes, bins=50, edgecolor=’black’)
[Link](donnees_completes.mean() + 3 * donnees_completes.std(),
color=’red’, linestyle=’--’, label=’Moyenne + 3 sigma’)
[Link]()
[Link](‘Detection de valeurs aberrantes’)
[Link]()

Distribution bimodale
Un histogramme révèle la présence de plusieurs modes (sommets) dans une distribution,
signe possible de deux sous-populations mélangées.

# données
[Link](2)
sous_population_1  [Link](40, 5, 500
sous_population_2  [Link](70, 8, 500
melange = [Link]([sous_population_1, sous_population_2
[Link](melange, bins=40, edgecolor=’black’, color=’mediumseagreen’)
# personnalisation
[Link](‘Valeur’)
[Link](‘Effectif’)
[Link](‘Distribution bimodale’)
[Link]()
La fonction hist() 47

Bonnes pratiques

• Toujours a icher le contour des barres avec edgecolor=’black’ : sans contour, les barres
adjacentes se confondent visuellement.
• Tester plusieurs valeurs de classes : la forme apparente d’une distribution dépend
fortement du nombre de classes. Commencer par bins=’auto’ puis ajuster.
• Utiliser density=True pour comparer des échantillons de tailles di érentes : sinon, le plus
grand écrase le plus petit.
• Pour superposer plusieurs histogrammes : préférer histtype=’step’ (contours), ou
alpha=0.5 pour la transparence.
• Ne pas confondre histogramme et diagramme en barres : pour des catégories discrètes,
utiliser bar(), pas hist().
• Étiqueter l’axe des ordonnées sans ambiguïté : "E ectif", "Fréquence (%)" ou "Densité"
selon le choix de normalisation.
• Penser à fixer range quand on compare plusieurs histogrammes : sans cela, chacun
utilise ses propres bornes et la comparaison devient trompeuse.

Conclusion

La fonction hist() est l’outil fondamental de l’analyse exploratoire de données : en quelques


lignes, elle permet de visualiser la distribution d’une variable numérique, de détecter des
anomalies et de formuler des hypothèses statistiques. Sa simplicité d’usage masque une
grande richesse paramétrique, notamment à travers le choix des classes, des styles et des
options de normalisation.
Pour des analyses plus poussées, on se tourne souvent vers des variantes complémentaires
comme plt.hist2d() pour les histogrammes bidimensionnels, [Link]() pour les diagrammes
en boîte (résumé synthétique de distribution), ou encore la fonction kdeplot() de Seaborn
qui produit une estimation lissée de la densité, plus élégante qu’un histogramme pour les
communications formelles. L’histogramme reste néanmoins le point de départ incontournable
de toute exploration statistique.
Habiller un graphique F06
Un graphique e icace ne se limite pas au tracé des données. Il doit aussi guider la lecture
avec un titre explicite, une identification des di érentes courbes, des repères visuels pour
apprécier les valeurs. Matplotlib propose trois fonctions dédiées à ces aspects :
• [Link]() : ajoute une grille de repérage en arrière-plan.
• [Link]() : a iche la légende associant couleurs ou styles à des libellés.
• [Link]() : ajoute un titre au graphique.
Ces trois fonctions sont complémentaires et font partie de tout graphique bien habillé. Leur
maîtrise transforme un tracé brut en une visualisation professionnelle, prête à être publiée ou
présentée.

Importation des bibliothèques

import [Link] as plt


import numpy as np
50 Habiller un graphique

La fonction grid()

La fonction grid() a iche une grille en arrière-plan du graphique. Cette grille aide le lecteur
à évaluer plus précisément les valeurs numériques en prolongeant mentalement les lignes
jusqu’aux axes. Par défaut, elle est désactivée.
Sa syntaxe est [Link](visible=None, which=’major’, axis=’both’, **kwargs). Les paramètres
principaux sont :
• visible : True pour a icher, False pour masquer.
• which : sur quelles graduations (ticks) s’appliquer (‘major’, ‘minor’ ou ‘both’).
• axis : axe concerné (‘x’, ‘y’ ou ‘both’).
• **kwargs : arguments de ligne (color, linestyle, linewidth, alpha).

Utilisation simple

x = [Link](0, 10, 100


y = [Link](x)
[Link](x, y)
[Link](True) # active la grille
[Link]()

Un simple appel à [Link]() (sans argument) bascule l’état de la grille. On lui préfère plt.
grid(True) pour plus de clarté.

Personnalisation
Une grille trop marquée distrait l’œil. On la veut généralement discrète.

[Link](x, y)
[Link](True,
color=’gray’,
linestyle=’--’,
linewidth=0.5,
alpha=0.7
[Link]()

Grille partielle
On peut n’a icher la grille que sur un axe.
Habiller un graphique 51
[Link](x, y)
[Link](True, axis=’y’) # grille horizontale uniquement
[Link]()

Cette option est particulièrement utile pour les diagrammes en barres verticales : seules les
lignes horizontales sont pertinentes, les verticales n’apportent rien.

Grille majeure et mineure

Matplotlib distingue les ticks majeurs (les graduations principales, numérotées) et les ticks
mineurs (subdivisions plus fines). On peut avoir une grille di érente pour chacun.

[Link](x, y)
plt.minorticks_on() # active les ticks mineurs
[Link](True, which=’major’, color=’gray’, linestyle=’-’, linewidth=0.8
[Link](True, which=’minor’, color=’lightgray’, linestyle=’:’, linewidth=0.5
[Link]()

La fonction legend()

La fonction legend() a iche un encart explicatif indiquant à quelle série correspond chaque
couleur, style ou marqueur. C’est un élément indispensable dès qu’un graphique contient
plusieurs séries, et le seul moyen conventionnel d’éviter de commenter les couleurs dans le
texte explicatif.
Sa syntaxe est [Link](handles=None, labels=None, loc=’best’, title=None, fontsize=None,
frameon=True, ncol=1, **kwargs).

Utilisation recommandée via label

La façon la plus propre d’utiliser legend() est de passer un argument label à chaque appel de
plot() (ou scatter(), bar(), etc), puis d’appeler legend() sans argument.

x = [Link](0, 2 * [Link], 100


[Link](x, [Link](x), label=’sin(x)’)
[Link](x, [Link](x), label=’cos(x)’)
[Link](x, [Link](x) * [Link](x), label=’sin(x)·cos(x)’)
[Link]()
[Link]()
52 Habiller un graphique

Astuce : les séries sans label (ou dont le label commence par un underscore ‘_’) sont
automatiquement ignorées par la légende. C’est pratique pour exclure par exemple une
courbe de référence.

Positionnement
Le paramètre loc contrôle la position de la légende. Les valeurs possibles sont :

Valeur Position
‘best’ placement automatique (par défaut)
‘upper right’ en haut à droite
‘upper left’ en haut à gauche
‘lower right’ en bas à droite
‘lower left’ en bas à gauche
‘center’ au centre
‘center left’ centrée sur le bord gauche
‘center right’ centrée sur le bord droit
‘upper center’ centrée en haut
‘lower center’ centrée en bas

[Link](loc=’upper right’)
[Link](loc=’lower left’)

Positionnement hors graphique


Pour placer la légende à l’extérieur du graphique (utile quand il y a beaucoup d’éléments), on
combine loc avec bbox_to_anchor.

[Link](x, [Link](x), label=’sin(x)’)


[Link](x, [Link](x), label=’cos(x)’)
[Link](loc=’upper left’, bbox_to_anchor=(1.02, 1 # a droite du graphique
plt.tight_layout()
[Link]()

Le tuple bbox_to_anchor=(1.02, 1) désigne un point d’ancrage exprimé en coordonnées


Habiller un graphique 53
relatives aux axes : (0, 0) correspond au coin inférieur gauche et (1, 1) au coin supérieur droit.
Un appel à plt.tight_layout() est généralement nécessaire pour éviter que la légende ne soit
coupée.

Personnalisation
Plusieurs paramètres a inent l’apparence :
• title : titre de la légende elle-même.
• fontsize : taille du texte.
• frameon : False pour supprimer l’encadrement.
• ncol : nombre de colonnes (utile quand il y a beaucoup d’entrées).
• shadow : ombre portée.
• framealpha : transparence de l’arrière-plan.

[Link](x, [Link](x), label=’sin(x)’)


[Link](x, [Link](x), label=’cos(x)’)
[Link](x, [Link](x), label=’tan(x)’)
[Link](title=’Fonctions’,
loc=’upper right’,
fontsize=10,
ncol=3,
framealpha=0.9,
shadow=True)
[Link]()

Spécifier manuellement les éléments


On peut aussi définir les libellés directement dans l’appel à legend(), en ignorant les label des
tracés. C’est moins lisible mais parfois utile.

[Link](x, [Link](x))
[Link](x, [Link](x))
[Link]([‘Sinus’, ‘Cosinus’])
[Link]()

Attention - Cette syntaxe est positionnelle : l’ordre des libellés doit correspondre exactement
à l’ordre des tracés. La méthode avec label= reste plus robuste aux modifications ultérieures
du code.
54 Habiller un graphique

La fonction title()

La fonction title() ajoute un titre au-dessus du graphique. Le titre doit résumer en quelques
mots le sujet du graphique, répondant à la question : "qu’est-ce que je regarde ?". Un bon titre
est court, explicite et autonome (compréhensible sans le texte qui l’entoure).
Sa syntaxe est [Link](label, fontdict=None, loc=’center’, pad=None, **kwargs). Les paramètres
principaux sont :
• label : texte du titre.
• loc : alignement horizontal (‘center’, ‘left’, ‘right’).
• pad : espacement entre le titre et le graphique (en points).
• fontsize, fontweight, color, fontstyle : mise en forme du texte.

Utilisation simple

[Link](x, [Link](x))
[Link](‘Courbe du sinus’)
[Link]()

Personnalisation de la mise en forme

[Link](x, [Link](x))
[Link](‘Courbe du sinus’,
fontsize=16,
fontweight=’bold’,
color=’navy’,
pad=15
[Link]()

Alignement

[Link](‘Titre a gauche’, loc=’left’)


[Link](‘Titre au centre’, loc=’center’)
[Link](‘Titre a droite’, loc=’right’)

Remarque : trois appels successifs à title() avec des loc di érents permettent d’a icher
simultanément un titre à gauche, au centre et à droite (par exemple un titre principal au centre
et une date à droite).
Habiller un graphique 55

Titres multi-lignes

On insère un saut de ligne avec \n : [Link](‘Distribution des notes\nPromotion 2024-2025’,


fontsize=14).

Titres mathématiques (LaTeX)

Matplotlib supporte une syntaxe de type LaTeX pour a icher des formules mathématiques. Le
texte mathématique est délimité par des $.

[Link](x, [Link](x) ** 2
[Link](r’Courbe de $f(x) = \sin^2(x)$’)
[Link]()

Le préfixe r avant la chaîne la transforme en raw string : les caractères backslash sont
interprétés littéralement, ce qui est indispensable pour les commandes LaTeX comme \sin, \
alpha, \sum, etc.

Titre de figure vs titre d’axes

Il existe une distinction importante :


• [Link]() : titre du graphique actuel (un seul axe).
• [Link]() : titre de la figure entière, au-dessus de tous les sous-graphiques.
Cette distinction devient essentielle quand on utilise [Link]() pour créer plusieurs
graphiques dans une même figure.

# sous-graphiques
[Link](1, 2, 1
[Link](x, [Link](x))
[Link](‘Sinus’)
[Link](1, 2, 2
[Link](x, [Link](x))
[Link](‘Cosinus’)
# graphique global
[Link](‘Fonctions trigonometriques’, fontsize=16
plt.tight_layout()
[Link]()
56 Habiller un graphique

Exemple combiné

Les trois fonctions sont systématiquement utilisées ensemble pour produire un graphique
soigné.

import numpy as np
import [Link] as plt
# Donnees fictives : ventes trimestrielles
trimestres = [‘T1’, ‘T2’, ‘T3’, ‘T4’]
produit_a = [120, 145, 160, 180
produit_b = [100, 130, 155, 175
produit_c = [80, 95, 110, 130
[Link](figsize=(10, 6
[Link](trimestres, produit_a, ‘o-’, linewidth=2, label=’Produit A’)
[Link](trimestres, produit_b, ‘s--’, linewidth=2, label=’Produit B’)
[Link](trimestres, produit_c, ‘^:’, linewidth=2, label=’Produit C’)
[Link](‘Evolution des ventes trimestrielles’, fontsize=14, fontweight=’bold’, pad=15
[Link](‘Trimestre’, fontsize=12
[Link](‘Ventes (milliers d\’unites)’, fontsize=12
[Link](True, linestyle=’--’, alpha=0.5, axis=’y’)
[Link](title=’Gamme’, loc=’upper left’, fontsize=10, framealpha=0.9
plt.tight_layout()
[Link]()

Cet exemple combine l’ensemble des bonnes pratiques : titre explicite et mis en valeur,
légende titrée et bien positionnée, grille horizontale discrète facilitant la lecture des valeurs,
et étiquettes d’axes claires avec unités.

Bonnes pratiques

Pour grid() :
• Toujours utiliser une grille discrète : lignes fines, couleur grise, transparence alpha=0.3 à
alpha=0.5. Une grille trop visible distrait de la donnée.
• Grille horizontale uniquement pour les barres verticales : les lignes verticales sont
superflues sur un bar() classique.
• Éviter la grille sur les camemberts et nuages de points denses : elle ajoute du bruit visuel
sans aider la lecture.
Habiller un graphique 57
Pour legend() :
• Toujours utiliser label= dans les appels de tracé plutôt que de passer les libellés à legend()
positionnellement.
• Préférer loc=’best’ dans un premier temps : Matplotlib choisit la zone la moins occupée.
Ajuster manuellement seulement si le résultat n’est pas satisfaisant.
• Placer la légende à l’extérieur (via bbox_to_anchor) quand elle masque des données
importantes ou contient beaucoup d’entrées.
• Utiliser ncol pour les légendes avec plus de 4 ou 5 entrées, afin d’éviter une liste verticale
démesurée.
Pour title() :
• Titre court et explicite : entre 3 et 10 mots idéalement. Il doit pouvoir être compris hors
contexte.
• Éviter les titres redondants avec les axes. "Graphique de x en fonction de y" n’apporte rien
si les axes sont déjà étiquetés.
• Distinguer title() et suptitle() : le premier titre chaque sous-graphique individuellement, le
second coi e l’ensemble de la figure.
• Utiliser fontweight=’bold’ pour hiérarchiser visuellement le titre par rapport aux étiquettes
d’axes.

Conclusion

Les fonctions grid(), legend() et title() constituent le trio indispensable pour habiller un graphique
Matplotlib. Individuellement, chacune joue un rôle précis : la grille facilite la lecture des
valeurs, la légende identifie les séries, et le titre informe sur le sujet du graphique. Ensemble,
elles transforment un simple tracé en une visualisation autonome et compréhensible par un
lecteur extérieur.
Ces fonctions font partie d’une famille plus large d’outils d’habillage :
• [Link]() et [Link]() pour les étiquettes d’axes.
• [Link]() et [Link]() pour les bornes.
• [Link]() et [Link]() pour personnaliser les graduations.
• [Link]() pour ajouter des commentaires ciblés.
Leur utilisation systématique est la marque d’un graphique de qualité publication.
Positionner plusieurs graphiques
avec la fonction subplot() F07
Jusqu’à présent, tous les tracés présentés étaient a ichés dans une seule zone graphique.
La fonction subplot() permet de placer plusieurs graphiques dans une même figure, en les
organisant selon une grille rectangulaire. Cette disposition est particulièrement utile pour :
• Comparer plusieurs jeux de données côte à côte.
• Présenter di érentes vues d’un même phénomène (par exemple une courbe et son
histogramme).
• Construire des tableaux de bord synthétiques.
• Séparer des courbes dont les échelles sont incompatibles.
Avant d’aller plus loin, il faut bien distinguer deux concepts :
• La figure (figure) : le conteneur global, équivalent à une feuille de papier. Il n’y en a
généralement qu’une à la fois.
• Les axes (axes qui est le terme anglais trompeur) : chaque zone de tracé individuelle à
l’intérieur de la figure. Une figure peut contenir plusieurs axes.
La fonction subplot() crée et sélectionne l’un de ces axes dans une grille prédéfinie.

Importation des bibliothèques

import [Link] as plt


import numpy as np
60 Positionner plusieurs graphiques avec la fonction subplot()

Syntaxe générale

La fonction accepte deux formes équivalentes :


• [Link](nrows, ncols, index)
• [Link](nrows * 100 + ncols * 10 + index)
Les paramètres sont :
• nrows : nombre de lignes de la grille.
• ncols : nombre de colonnes de la grille.
• index : position du graphique dans la grille (numérotée à partir de 1).
La forme compacte à trois chi res [Link](nmp) où n est le nombre de lignes, m le nombre
de colonnes, et p l’index, est très fréquente dans le code existant.

[Link](2, 3, 1 # grille 23, graphique 1


[Link](231) # equivalent (mais limite a des chiffres < 10

Attention : la forme compacte ne fonctionne que si les trois nombres sont inférieurs à 10. Pour
une grille plus grande (ex. 2x11), il faut obligatoirement utiliser la forme à trois arguments.

Numérotation des positions

Les positions sont numérotées à partir de 1 (et non 0 comme en Python habituellement), ligne
par ligne, de gauche à droite, de haut en bas. C’est le sens de lecture occidental d’un texte.
Pour une grille 2x3 par exemple.

1 2 3
4 5 6

Chaque appel à subplot() définit l’axe actif. Les commandes Matplotlib qui suivent (plot(),
title(), xlabel(), etc) s’appliquent uniquement à cet axe, jusqu’au prochain subplot().

Premier exemple

Deux graphiques côte à côte, sur une ligne.

import [Link] as plt


import numpy as np
x = [Link](0, 2 * [Link], 100
Positionner plusieurs graphiques avec la fonction subplot() 61
# Premier graphique (gauche)
[Link](1, 2, 1
[Link](x, [Link](x))
[Link](‘Sinus’)
# Second graphique (droite)
[Link](1, 2, 2
[Link](x, [Link](x))
[Link](‘Cosinus’)
[Link]()

Variante avec trois graphiques empilés verticalement.

[Link](3, 1, 1
[Link](x, [Link](x))
[Link](‘Sinus’)
[Link](3, 1, 2
[Link](x, [Link](x))
[Link](‘Cosinus’)
[Link](3, 1, 3
[Link](x, [Link](x))
[Link](‘Tangente’)
[Link](-10, 10
plt.tight_layout()
[Link]()

L’appel à plt.tight_layout() est quasi indispensable dès qu’on utilise plusieurs sous-graphiques
(subplots) : il ajuste automatiquement les espacements pour éviter que les titres et les
étiquettes se chevauchent.

Grille complète

Pour une grille 2x2 avec quatre graphiques di érents.

x = [Link](-3, 3, 100
[Link](figsize=(10, 8
[Link](2, 2, 1
[Link](x, x)
[Link](‘Identite’)
62 Positionner plusieurs graphiques avec la fonction subplot()

[Link](2, 2, 2
[Link](x, x ** 2
[Link](‘Carre’)
[Link](2, 2, 3
[Link](x, x ** 3
[Link](‘Cube’)
[Link](2, 2, 4
[Link](x, [Link](x))
[Link](‘Exponentielle’)
plt.tight_layout()
[Link]()

L’appel à [Link](figsize=(10, 8)) fixe la taille globale de la figure en pouces. Sans cela, la
figure par défaut (souvent 6x4) devient vite à l’étroit avec plusieurs subplots.

Graphiques de tailles différentes

On peut donner plus de place à un graphique en lui faisant occuper plusieurs cellules. Pour
cela, on choisit une grille fine, et chaque subplot() est appelé avec l’index de la première cellule
qu’il occupe, mais Matplotlib redimensionne automatiquement. Cependant, la fonction
subplot() seule ne permet pas facilement de faire chevaucher plusieurs cellules. Pour cela,
on utilise plt.subplot2grid().

[Link](figsize=(12, 8
# Grille de reference : 3 lignes x 3 colonnes
# Grand graphique occupant 2 lignes et 2 colonnes
axe_principal = plt.subplot2grid((3, 3, 0, 0, rowspan=2, colspan=2
axe_principal.plot([Link](100).cumsum())
axe_principal.set_title(‘Principal’)
# Trois petits graphiques
plt.subplot2grid((3, 3, 0, 2
[Link]([Link](20))
[Link](‘Detail 1’)
plt.subplot2grid((3, 3, 1, 2
[Link]([Link](20))
[Link](‘Detail 2’)
plt.subplot2grid((3, 3, 2, 0, colspan=3
[Link]([Link](50))
Positionner plusieurs graphiques avec la fonction subplot() 63
[Link](‘Bande inferieure’)
plt.tight_layout()
[Link]()

Les paramètres de subplot2grid() sont :


• shape : tuple (nrows, ncols) définissant la grille.
• loc : tuple (ligne, colonne) de la cellule de départ (numérotée à partir de 0, contrairement
à subplot()).
• rowspan : nombre de lignes occupées (défaut 1).
• colspan : nombre de colonnes occupées (défaut 1).

L’alternative [Link]()

Matplotlib propose une fonction pluriel [Link]() (avec un s) qui crée toute la grille d’un
seul appel, plus élégante que plusieurs [Link]() successifs. Elle retourne la figure et un
tableau d’axes.

# graphique
figure, tableau_axes = [Link](2, 3, figsize=(12, 6
# tableau_axes est un tableau numpy 2D
tableau_axes[0, 0].plot(x, [Link](x))
tableau_axes[0, 0].set_title(‘Sinus’)
tableau_axes[0, 1].plot(x, [Link](x))
tableau_axes[0, 1].set_title(‘Cosinus’)
tableau_axes[0, 2].plot(x, [Link](x))
tableau_axes[0, 2].set_title(‘Tangente’)
tableau_axes[1, 0].plot(x, x ** 2
tableau_axes[1, 0].set_title(‘Carre’)
tableau_axes[1, 1].plot(x, x ** 3
tableau_axes[1, 1].set_title(‘Cube’)
tableau_axes[1, 2].plot(x, [Link](x))
tableau_axes[1, 2].set_title(‘Exponentielle’)
plt.tight_layout()
[Link]()

Di érences importantes avec subplot() :


• Les méthodes s’appellent set_title() et non title() (idem pour set_xlabel(), set_ylabel(), set_
xlim(), etc).
• La méthode plot() s’applique directement sur l’axe : tableau_axes[0, 0].plot(...).
64 Positionner plusieurs graphiques avec la fonction subplot()

• Cette approche est plus lisible pour les grilles étendues et s’intègre mieux dans un code
Python structuré.

Cas particulier d’une seule ligne ou colonne


Quand la grille n’a qu’une ligne (ou qu’une colonne), [Link]() retourne un tableau
unidimensionnel.

figure, tableau_axes = [Link](1, 3, figsize=(12, 4


tableau_axes[0].plot(x, [Link](x))
tableau_axes[1].plot(x, [Link](x))
tableau_axes[2].plot(x, [Link](x))
plt.tight_layout()
[Link]()

Partage d’axes entre subplots

Quand plusieurs graphiques ont la même plage de valeurs sur un axe, on peut les lier : les
bornes deviennent synchronisées, et les étiquettes intermédiaires sont automatiquement
masquées pour gagner de la place. Cette fonctionnalité est disponible via sharex et sharey
dans [Link]().

# graphique
figure, tableau_axes = [Link](2, 1, figsize=(10, 6, sharex=True)
x = [Link](0, 10, 200
tableau_axes[0].plot(x, [Link](x))
tableau_axes[0].set_title(‘Sinus’)
tableau_axes[0].set_ylabel(‘y’)
tableau_axes[1].plot(x, [Link](x))
tableau_axes[1].set_title(‘Cosinus’)
tableau_axes[1].set_xlabel(‘x’)
tableau_axes[1].set_ylabel(‘y’)
# affichage
plt.tight_layout()
[Link]()

Avec sharex=True, les deux graphiques partagent l’axe horizontal : zoomer sur l’un zoome sur
l’autre, et l’axe n’est étiqueté qu’en bas.
Positionner plusieurs graphiques avec la fonction subplot() 65

Cas d’usage courants

Courbe et son histogramme


Associer une série temporelle à la distribution de ses valeurs.

[Link](0)
donnees = [Link](1000).cumsum()
[Link](figsize=(12, 4
[Link](1, 2, 1
[Link](donnees)
[Link](‘Serie temporelle’)
[Link](‘Temps’)
[Link](‘Valeur’)
[Link](True, alpha=0.3
[Link](1, 2, 2
[Link](donnees, bins=30, edgecolor=’black’)
[Link](‘Distribution des valeurs’)
[Link](‘Valeur’)
[Link](‘Effectif’)
plt.tight_layout()
[Link]()

Comparaison avant / après

[Link](1)
avant = [Link](50, 15, 500
apres = [Link](60, 10, 500
figure, tableau_axes = [Link](1, 2, figsize=(12, 5, sharey=True)
tableau_axes[0].hist(avant, bins=25, color=’lightcoral’, edgecolor=’black’)
tableau_axes[0].set_title(‘Avant’)
tableau_axes[0].set_xlabel(‘Valeur’)
tableau_axes[0].set_ylabel(‘Effectif’)
tableau_axes[1].hist(apres, bins=25, color=’lightgreen’, edgecolor=’black’)
tableau_axes[1].set_title(‘Apres’)
tableau_axes[1].set_xlabel(‘Valeur’)
[Link](‘Comparaison avant / apres traitement’, fontsize=14
66 Positionner plusieurs graphiques avec la fonction subplot()

plt.tight_layout()
[Link]()

Tableau de bord synthétique

[Link](2)
figure, tableau_axes = [Link](2, 2, figsize=(12, 8
# Haut gauche : evolution
tableau_axes[0, 0].plot([Link](100).cumsum(), color=’steelblue’)
tableau_axes[0, 0].set_title(‘Evolution’)
tableau_axes[0, 0].grid(True, alpha=0.3
# Haut droite : repartition par categorie
categories = [‘A’, ‘B’, ‘C’, ‘D’]
valeurs = [23, 45, 56, 38
tableau_axes[0, 1].bar(categories, valeurs, color=’coral’)
tableau_axes[0, 1].set_title(‘Repartition’)
# Bas gauche : correlation
x = [Link](50)
y = 2 * x + [Link](0, 0.2, 50
tableau_axes[1, 0].scatter(x, y, alpha=0.6
tableau_axes[1, 0].set_title(‘Correlation’)
# Bas droite : distribution
tableau_axes[1, 1].hist(
[Link](100, 15, 500,
bins=30, color=’mediumseagreen’,
edgecolor=’black’)
tableau_axes[1, 1].set_title(‘Distribution’)
[Link](‘Tableau de bord’, fontsize=16, fontweight=’bold’)
plt.tight_layout()
[Link]()

Ajustements fins de l’espacement

Quand tight_layout() ne su it pas, on contrôle l’espacement avec plt.subplots_adjust().

plt.subplots_adjust(
left=0.1, # marge gauche
Positionner plusieurs graphiques avec la fonction subplot() 67
right=0.95, # marge droite
bottom=0.1, # marge basse
top=0.9, # marge haute
wspace=0.3, # espace horizontal entre subplots
hspace=0.4 # espace vertical entre subplots
)

Les valeurs sont exprimées en fraction de la largeur ou hauteur de la figure (entre 0 et 1). Les
paramètres wspace et hspace sont les plus fréquemment ajustés quand les étiquettes se
superposent.

Bonnes pratiques

• Toujours appeler plt.tight_layout() avant [Link]() quand il y a plusieurs subplots : sans


cela, titres et étiquettes se chevauchent systématiquement.
• Dimensionner la figure avec [Link](figsize=...) ou l’argument figsize de [Link]().
Une règle utile : environ 4 à 5 pouces par subplot.
• Préférer [Link]() à [Link]() dans les scripts structurés : plus lisible, plus flexible,
et c’est l’approche recommandée par la documentation moderne de Matplotlib.
• Utiliser sharex et sharey quand les graphiques ont des axes comparables : cela économise
de la place et force la comparaison équitable.
• Ajouter un suptitle() pour coi er l’ensemble quand les subplots traitent un thème commun.
• Ne pas abuser des subplots : au-delà de 6 graphiques dans une même figure, la lisibilité
chute. Envisager alors plusieurs figures séparées.
• Respecter une grille uniforme quand c’est possible : les grilles irrégulières (subplot2grid)
sont réservées aux cas où la hiérarchie visuelle est nécessaire (un graphique principal et
des détails secondaires).

Conclusion

La fonction subplot() permet d’organiser plusieurs graphiques dans une grille rectangulaire,
transformant une simple figure en véritable support de communication. Sa syntaxe (nrows,
ncols, index) est simple à retenir, à condition de garder en tête que la numérotation commence
à 1 et suit le sens de lecture.
Pour des besoins plus élaborés, Matplotlib o re plusieurs alternatives complémentaires : plt.
subplots() pour créer toute une grille d’un coup avec une API orientée objet plus propre, plt.
subplot2grid() pour des graphiques de tailles inégales, et [Link] pour
les mises en page les plus sophistiquées (avec des largeurs et hauteurs personnalisées par
ligne et colonne). La maîtrise de subplot() et de ses variantes est la clé pour passer d’un simple
utilisateur de Matplotlib à un producteur de visualisations structurées et professionnelles.
Intégrer des tableaux
avec la fonction table() F08
La fonction table() de Matplotlib permet d’ajouter un tableau de données directement dans
une figure graphique. Cette fonctionnalité, moins connue que plot() ou bar(), répond à un
besoin fréquent : présenter les valeurs chi rées qui ont servi à construire un graphique, ou
a icher un récapitulatif synthétique à côté d’une visualisation.
L’usage typique consiste à placer un tableau en bas d’un graphique en barres ou d’une
courbe, pour que le lecteur puisse à la fois percevoir les tendances visuellement et lire les
chi res exacts. Cette combinaison graphique + tableau est particulièrement e icace dans les
rapports et présentations.
Note importante : la fonction table() n’est pas destinée à remplacer un vrai outil de mise en
forme de tableaux comme Pandas. Elle est conçue pour l’intégration graphique, pas pour le
calcul ou la manipulation de données tabulaires.

Importation des bibliothèques

import [Link] as plt


import numpy as np
70 Intégrer des tableaux avec la fonction table()

Syntaxe générale

La signature simplifiée de la fonction est [Link](cellText=None, cellColours=None,


rowLabels=None, rowColours=None, colLabels=None, colColours=None, loc=’bottom’,
bbox=None, colWidths=None, cellLoc=’right’, **kwargs). Les paramètres principaux sont :
• cellText : contenu des cellules, sous forme de liste 2D (lignes de listes).
• cellColours : couleurs de fond des cellules (même structure que cellText).
• rowLabels : libellés a ichés en début de chaque ligne.
• rowColours : couleurs de fond des libellés de lignes.
• colLabels : libellés des colonnes (en-têtes).
• colColours : couleurs de fond des en-têtes de colonnes.
• loc : position du tableau dans la figure (‘bottom’ par défaut).
• colWidths : largeurs relatives des colonnes.
• cellLoc : alignement du texte dans les cellules (‘left’, ‘center’, ‘right’).
Valeur de retour : la fonction retourne un objet Table que l’on peut manipuler ensuite pour
a iner la mise en forme (taille de police, échelle, ajustements fins).

Premier exemple

Un tableau minimal a iché seul dans une figure.

import [Link] as plt


donnees = [[‘Paris’, 2_145_000, 105, [‘Lyon’, 515_000, 48,
[‘Marseille’, 870_000, 240, [‘Toulouse’, 498_000, 118
en_tetes = [‘Ville’, ‘Population’, ‘Superficie (km2)’]
[Link](figsize=(8, 3
[Link](‘off’) # masque les axes
[Link](
cellText=donnees,
colLabels=en_tetes,
loc=’center’
)
[Link]()

L’appel à [Link](‘o ’) est essentiel : sans cela, les axes du graphique (inutiles ici) apparaissent
en arrière-plan du tableau. Le paramètre loc=’center’ centre le tableau verticalement dans la
zone disponible.
Intégrer des tableaux avec la fonction table() 71

Associer un tableau à un graphique

C’est l’usage le plus courant : placer le tableau sous un graphique en barres ou une courbe.

import [Link] as plt


import numpy as np
trimestres = [‘T1’, ‘T2’, ‘T3’, ‘T4’]
produit_a = [120, 145, 160, 180
produit_b = [100, 130, 155, 175
[Link](figsize=(9, 6
# Graphique en barres groupees
positions = [Link](len(trimestres))
largeur = 0.35
[Link](positions - largeur/2, produit_a, largeur, label=’Produit A’, color=’steelblue’)
[Link](positions + largeur/2, produit_b, largeur, label=’Produit B’, color=’coral’)
[Link](positions, trimestres)
[Link](‘Ventes’)
[Link](‘Ventes trimestrielles’)
[Link]()
# Tableau recapitulatif sous le graphique
donnees_tableau = [produit_a, produit_b]
libelles_lignes = [‘Produit A’, ‘Produit B’]
[Link](cellText=donnees_tableau,
rowLabels=libelles_lignes,
colLabels=trimestres,
loc=’bottom’,
cellLoc=’center’)
# Ajustement pour laisser la place au tableau
plt.subplots_adjust(bottom=0.25
[Link]([]) # masque les ticks de l’axe x, remplaces par le tableau
[Link]()

Deux ajustements sont nécessaires pour une intégration propre :


• plt.subplots_adjust(bottom=0.25) : libère de l’espace en bas de la figure pour le tableau.
• [Link]([]) : supprime les étiquettes de l’axe X, devenues redondantes avec les en-têtes
du tableau.
72 Intégrer des tableaux avec la fonction table()

Positionnement du tableau

Le paramètre loc accepte de nombreuses valeurs, analogues à celles de legend().

Valeur Position

‘bottom’ sous le graphique (par défaut)

‘top’ au-dessus du graphique

‘left’ à gauche du graphique

‘right’ à droite du graphique

‘center’ au centre (utile avec axis(‘o ’))

‘upper right’ en haut à droite (dans le graphique)

‘upper left’ en haut à gauche (dans le graphique)

‘lower right’ en bas à droite (dans le graphique)

‘lower left’ en bas à gauche (dans le graphique)

Pour un contrôle complet de la position, on utilise l’argument bbox qui accepte un tuple (x, y,
largeur, hauteur) en coordonnées relatives aux axes (entre 0 et 1).

[Link](
cellText=donnees,
colLabels=en_tetes,
bbox=[0.2, 0.1, 0.6, 0.3 # x, y, largeur, hauteur
)

Mise en forme du tableau

Couleurs de fond
Les paramètres cellColours, rowColours et colColours permettent de colorer le fond des
cellules, en-têtes de lignes et en-têtes de colonnes.
Intégrer des tableaux avec la fonction table() 73
donnees = [[‘Paris’, 2145, 105, [‘Lyon’, 515, 48, [‘Marseille’, 870, 240
en_tetes = [‘Ville’, ‘Population (k)’, ‘Superficie (km2)’]
libelles_lignes = [‘Ligne 1’, ‘Ligne 2’, ‘Ligne 3’]
# Couleurs en-tetes : une par colonne
couleurs_colonnes = [‘#4472C4’] * 3
# Couleurs lignes : une par ligne
couleurs_lignes = [‘#D9E1F2’] * 3
[Link](figsize=(8, 3
[Link](‘off’)
[Link](cellText=donnees,
colLabels=en_tetes,
rowLabels=libelles_lignes,
colColours=couleurs_colonnes,
rowColours=couleurs_lignes,
loc=’center’,
cellLoc=’center’)
[Link]()

Coloration conditionnelle
Le paramètre cellColours est particulièrement puissant : il accepte une liste 2D de couleurs
de même forme que cellText, ce qui permet de colorer chaque cellule individuellement selon
sa valeur.

import numpy as np
import [Link] as plt
# Donnees : resultats par eleve et par matiere
notes = [[15, 12, 8, 18, 14, 11, 9, 7, 13, 16, 17, 15
eleves = [‘Alice’, ‘Bob’, ‘Chloe’, ‘David’]
matieres = [‘Maths’, ‘Physique’, ‘Histoire’]
# Coloration conditionnelle
def couleur_selon_note(note):
if note >= 15
return ‘#A9DFBF’ # vert clair
elif note >= 10
return ‘#F9E79F’ # jaune clair
else:
return ‘#F5B7B1’ # rouge clair
74 Intégrer des tableaux avec la fonction table()

couleurs_cellules = [[couleur_selon_note(note) for note in ligne] for ligne in notes]


[Link](figsize=(8, 3
[Link](‘off’)
[Link](cellText=notes,
cellColours=couleurs_cellules,
rowLabels=eleves,
colLabels=matieres,
loc=’center’,
cellLoc=’center’)
[Link]()

Largeur des colonnes


Le paramètre colWidths accepte une liste de largeurs relatives (fractions de la largeur des
axes).

[Link](cellText=donnees, colLabels=en_tetes, colWidths=[0.3, 0.2, 0.2, loc=’center’)

Manipulation fine via l’objet Table

La valeur de retour de table() permet d’ajuster le tableau après sa création. Les méthodes les
plus utiles sont les suivantes.

mon_tableau = [Link](cellText=donnees, colLabels=en_tetes, loc=’center’)


# Desactiver le redimensionnement automatique de la police
mon_tableau.auto_set_font_size(False)
mon_tableau.set_fontsize(11)
# Agrandir le tableau (hauteur x 1.5, largeur x 1.2
mon_tableau.scale(1.2, 1.5

Pourquoi désactiver la taille automatique ? Par défaut, Matplotlib ajuste la taille du texte pour
que les cellules soient lisibles, mais ce calcul est souvent imparfait. On préfère fixer soi-
même la taille via set_fontsize() après avoir appelé auto_set_font_size(False).

Modifier une cellule individuelle


On accède aux cellules via la méthode get_celld() (ou par indexation directe) pour modifier
une cellule spécifique.

mon_tableau = [Link](cellText=donnees, colLabels=en_tetes, loc=’center’)


Intégrer des tableaux avec la fonction table() 75
# Les indices des en-tetes de colonnes commencent a (0, j)
# Les cellules de donnees commencent a (1, j) pour la premiere ligne
cellule = mon_tableau[1, 0] # ligne 1, colonne 0
cellule.set_facecolor(‘yellow’)
cellule.set_text_props(weight=’bold’, color=’darkred’)

Indexation : les clés sont des tuples (ligne, colonne). La ligne 0 correspond aux en-têtes
(colLabels), les données commencent donc à la ligne 1. Quand rowLabels est utilisé, la
colonne -1 correspond aux libellés de lignes.

Exemple complet

Cet exemple combine les techniques précédentes : un graphique en courbes surmontant un


tableau récapitulatif, avec coloration conditionnelle basée sur l’évolution.

import numpy as np
import [Link] as plt
annees = [2020, 2021, 2022, 2023, 2024, 2025
produit_a = [100, 110, 125, 135, 150, 165
produit_b = [80, 95, 92, 105, 118, 125
produit_c = [50, 65, 78, 90, 95, 110
[Link](figsize=(10, 7
# Graphique superieur
[Link](annees, produit_a, ‘o-’, label=’Produit A’, linewidth=2
[Link](annees, produit_b, ‘s--’, label=’Produit B’, linewidth=2
[Link](annees, produit_c, ‘^:’, label=’Produit C’, linewidth=2
[Link](‘Evolution des ventes’)
[Link](‘Chiffre d\’affaires (k EUR’
[Link]()
[Link](True, alpha=0.3
[Link]([])
# Preparation du tableau
donnees_brutes = [produit_a, produit_b, produit_c]
libelles_produits = [‘Produit A’, ‘Produit B’, ‘Produit C’]
# Coloration selon l’evolution entre deux annees consecutives
def couleur_evolution(val_precedente, val_actuelle):
if val_precedente is None:
76 Intégrer des tableaux avec la fonction table()

return ‘white’
if val_actuelle > val_precedente:
return ‘#D5F5E3’ # vert clair : progression
elif val_actuelle < val_precedente:
return ‘#FADBD8’ # rouge clair : recul
else:
return ‘#FCF3CF’ # jaune clair : stagnation
couleurs_donnees = []
for ligne_valeurs in donnees_brutes:
couleurs_ligne = [‘white’] # premiere colonne sans comparaison
for indice in range(1, len(ligne_valeurs)):
couleurs_ligne.append(
couleur_evolution(ligne_valeurs[indice - 1, ligne_valeurs[indice])
)
couleurs_donnees.append(couleurs_ligne)
mon_tableau = [Link](cellText=donnees_brutes,
cellColours=couleurs_donnees, rowLabels=libelles_produits,
colLabels=[str(a) for a in annees], loc=’bottom’,
cellLoc=’center’)
mon_tableau.auto_set_font_size(False)
mon_tableau.set_fontsize(10)
mon_tableau.scale(1, 1.5
plt.subplots_adjust(bottom=0.3
[Link]()

Limitations et alternatives

La fonction table() est pratique mais a plusieurs limitations qu’il faut connaître :
• Pas de fusion de cellules : impossible de créer des cellules qui s’étendent sur plusieurs
lignes ou colonnes.
• Formatage du texte limité : pas de support natif pour les formats numériques (séparateurs
de milliers, pourcentages, etc). Il faut pré-formater les chaînes avant de les passer.
• Mise en page figée : les ajustements fins (espacements, alignements individuels)
demandent du code répétitif.
• Performance : peu adapté aux tableaux de plus de 20-30 lignes, qui deviennent illisibles
dans une figure.
Alternatives : pour des tableaux complexes ou purement textuels, on préfère souvent :
• DataFrame de Pandas avec to_html() ou style dans un notebook.
Intégrer des tableaux avec la fonction table() 77
• La bibliothèque tabulate pour les sorties texte bien mises en forme.
• Un export direct en image via un moteur de rendu HTML si le tableau est complexe.

Bonnes pratiques

• Masquer les axes avec [Link](‘o ’) quand le tableau est a iché seul, sinon les axes du
graphique vide restent visibles en arrière-plan.
• Libérer de l’espace avec plt.subplots_adjust(bottom=...) quand le tableau est placé sous
un graphique.
• Supprimer les xticks redondants via [Link]([]) quand les en-têtes du tableau reprennent
les valeurs de l’axe.
• Pré-formater les nombres avant de les passer à cellText : utiliser f’{val:,.2f}’ ou des f-strings
similaires pour un rendu professionnel.
• Désactiver auto_set_font_size() et fixer la police manuellement pour un rendu
reproductible.
• Utiliser la coloration conditionnelle avec parcimonie : trois couleurs maximum, avec un
code couleur cohérent et intuitif (vert = bon, rouge = mauvais).
• Limiter le nombre de lignes : au-delà de 15 lignes, le tableau devient di icilement lisible
dans une figure. Envisager alors un tableau séparé (Pandas, HTML, etc).
• Éviter les tableaux purement décoratifs. Un tableau est justifié quand les valeurs exactes
complètent le graphique, pas quand elles le répètent inutilement.

Conclusion

La fonction table() est un outil spécialisé mais précieux pour enrichir un graphique avec les
données chi rées qui l’ont produit. Combinée à plot() ou bar(), elle permet de produire des
figures complètes dans lesquelles le lecteur accède à la fois à la tendance visuelle et aux
valeurs précises, ce qui est particulièrement apprécié dans les rapports professionnels.
Pour des usages plus avancés (tableaux avec cellules fusionnées, formatage riche,
interactivité), il faut se tourner vers des outils dédiés : Pandas pour la manipulation et l’export
HTML, [Link] pour du texte positionné librement, ou encore des
bibliothèques spécialisées comme plottable. Pour la plupart des besoins courants, table()
reste cependant le chemin le plus rapide pour intégrer quelques lignes de données dans un
graphique Matplotlib.
Annoter un graphique
avec la fonction text() F09
La fonction text() de Matplotlib permet de placer du texte libre à n’importe quelle position
d’un graphique. Contrairement à title(), xlabel() ou legend() qui occupent des emplacements
prédéfinis, text() o re un contrôle total sur la position du texte : on indique explicitement les
coordonnées où l’a icher. Cette flexibilité en fait un outil précieux pour :
• Annoter une valeur spécifique (pic, minimum, point remarquable).
• Ajouter un commentaire explicatif directement dans le graphique.
• A icher des statistiques calculées (moyenne, écart-type, nombre d’observations).
• Étiqueter individuellement des points dans un nuage de points.
• Insérer une source ou une date en coin de graphique.
La fonction text() est aussi le socle de fonctions plus spécialisées comme annotate() (qui
ajoute une flèche) ou xlabel() : les maîtriser nécessite de bien comprendre d’abord text().

Importation des bibliothèques

import [Link] as plt


import numpy as np
80 Annoter un graphique avec la fonction text()

Syntaxe générale

La signature simplifiée de la fonction est [Link](x, y, s, fontdict=None, **kwargs). Les paramètres


principaux sont :
• x : coordonnée horizontale où placer le texte.
• y : coordonnée verticale où placer le texte.
• s : la chaîne de caractères à a icher.
• fontdict : dictionnaire de propriétés de police (déprécié, utiliser les kwargs).
• **kwargs : arguments nommés (couleur, taille, alignement, rotation, etc).
Point crucial : par défaut, x et y sont exprimés dans les coordonnées des données, c’est-à-dire
dans le même système que les axes du graphique. Si l’axe X va de 0 à 100, alors [Link](50,
...) place le texte au milieu horizontal. Ce comportement peut être modifié via le paramètre
transform.

Premier exemple

Placer un simple texte dans un graphique.

import [Link] as plt


import numpy as np
x = [Link](0, 10, 100
y = [Link](x)
[Link](x, y)
[Link](5, 0.5, ‘Texte au milieu’)
[Link]()

Le texte apparaît à la position (5, 0.5) dans les coordonnées du graphique. Sans spécification
supplémentaire, le point d’ancrage est le coin inférieur gauche du texte.

Mise en forme du texte

De nombreux arguments nommés permettent de contrôler l’apparence du texte. Les plus


utiles sont les suivants.

Argument Description

fontsize Taille de police (nombre ou mot-clé : ‘small’, ‘large’, ‘xx-large’...)


Annoter un graphique avec la fonction text() 81

color Couleur du texte

fontweight Graisse : ‘normal’, ‘bold’, ‘light’, ou valeur numérique

fontstyle Style : ‘normal’, ‘italic’, ‘oblique’

fontfamily Police : ‘serif’, ‘sans-serif’, ‘monospace’...

rotation Angle de rotation en degrés

alpha Transparence entre 0 et 1

backgroundcolor Couleur de fond (simple rectangle)

bbox Dictionnaire pour un cadre décoratif autour du texte

Exemple

[Link](x, y)
[Link](5, 0.5,
‘Texte en evidence’,
fontsize=14,
fontweight=’bold’,
color=’darkred’,
fontstyle=’italic’)
[Link]()

Texte avec rotation


La rotation est particulièrement utile pour étiqueter des événements sur un axe temporel.

[Link](x, y)
[Link](3, color=’red’, linestyle=’--’, alpha=0.5
[Link](3.1, 0.8, ‘Evenement important’,
rotation=90,
fontsize=11,
color=’darkred’)
[Link]()
82 Annoter un graphique avec la fonction text()

Alignement et point d’ancrage

Par défaut, la position (x, y) correspond au coin inférieur gauche du texte. Pour d’autres
ancrages, on utilise horizontalalignment (abrégé ha) et verticalalignment (abrégé va).

Alignement horizontal

Valeur EƯet

‘left’ le bord gauche du texte est à x (défaut)

‘center’ le centre horizontal du texte est à x

‘right’ le bord droit du texte est à x

Alignement vertical

Valeur EƯet

‘top’ le haut du texte est à y

‘center’ le centre vertical du texte est à y

‘bottom’ le bas du texte est à y (défaut)

‘baseline’ la ligne de base typographique est à y

Exemple : centrer un texte sur un point

[Link](x, y)
[Link](5, [Link](5), ‘ro’, markersize=10
[Link](5, [Link](5),
‘Point cible’,
ha=’center’, va=’bottom’,
fontsize=11, color=’red’)
[Link]()

Avec ha=’center’ et va=’bottom’, le texte est centré horizontalement et placé juste au-dessus
du point (5, sin(5)).
Annoter un graphique avec la fonction text() 83

Systèmes de coordonnées (transform)

Par défaut, (x, y) sont exprimés dans les coordonnées des données. Pour placer du texte
indépendamment des données (par exemple toujours en haut à droite du graphique, quelles
que soient les échelles), on change le système de coordonnées via l’argument transform.

Coordonnées des axes


Avec transform=[Link]().transAxes, les coordonnées vont de (0, 0) (coin inférieur gauche des
axes) à (1, 1) (coin supérieur droit), indépendamment des valeurs réelles.

x = [Link](0, 1000, 100


y = [Link](100).cumsum()
[Link](x, y)
# Texte en haut a droite, independamment des echelles
[Link](0.95, 0.95,
‘Annotation fixe’,
transform=[Link]().transAxes,
ha=’right’, va=’top’,
fontsize=11,
bbox={‘facecolor’: ‘lightyellow’,
‘edgecolor’: ‘orange’,
‘boxstyle’: ‘round’})
[Link]()

L’appel à [Link]() récupère l’axe actif courant. Sa propriété transAxes est la transformation qui
fait correspondre les coordonnées relatives aux bords des axes.

Comparatif des systèmes

Transform Interprétation de (x, y)

transData (défaut) coordonnées des données

transAxes coordonnées relatives aux axes (0 à 1)

[Link] coordonnées relatives à la figure entière


84 Annoter un graphique avec la fonction text()

Encadrement du texte (bbox)

Le paramètre bbox permet d’entourer le texte d’un cadre décoratif. Il prend un dictionnaire de
propriétés.

Clé Description

Forme : ‘round’, ‘square’, ‘sawtooth’, ‘roundtooth’, ‘larrow’,


‘boxstyle’
‘rarrow’

‘facecolor’ Couleur de fond du cadre

‘edgecolor’ Couleur du contour

‘linewidth’ Épaisseur du contour

‘alpha’ Transparence du cadre

‘pad’ Marge intérieure entre le texte et le cadre

Exemples d’encadrement

[Link](x, y)
# Cadre arrondi avec fond jaune
[Link](2, 0.5, ‘Arrondi’,
bbox={‘boxstyle’: ‘round’,
‘facecolor’: ‘#FFF3B0’,
‘edgecolor’: ‘#C2A700’,
‘pad’ 0.5
# Cadre carre avec ombre
[Link](5, 0.5, ‘Carre’,
bbox={‘boxstyle’: ‘square’,
‘facecolor’: ‘lightblue’,
‘edgecolor’: ‘navy’,
‘linewidth’ 2
# Cadre fleche pointant a droite
[Link](8, 0.5, ‘Fleche’,
bbox={‘boxstyle’: ‘rarrow’,
Annoter un graphique avec la fonction text() 85
‘facecolor’: ‘lightgreen’})
[Link]()

Texte mathématique (LaTeX)

Comme pour title() et xlabel(), text() supporte une syntaxe de type LaTeX pour a icher des
formules mathématiques. Le texte mathématique est délimité par des $.

x = [Link](-3, 3, 100
y = [Link](-x ** 2
[Link](x, y)
[Link](0, 0.5,
r’$f(x) = e^{-x^2$’,
ha=’center’,
fontsize=16,
bbox={‘facecolor’: ‘white’, ‘edgecolor’: ‘black’})
[Link]()

Le préfixe r devant la chaîne (raw string) est indispensable : il empêche Python d’interpréter les
\ comme des séquences d’échappement, ce qui permet d’écrire \alpha, \sum, \int, etc.

Quelques exemples de syntaxe courante.

Syntaxe Rendu

r’$x^2$’ x au carré (exposant)

r’$x_i$’ x indice i

r’$\alpha, \beta, \gamma$’ lettres grecques

r’$\frac{a}{b}$’ fraction a sur b

r’$\sqrt{x}$’ racine carrée de x

r’$\sum_{i=1}^{n}$’ somme indexée

r’$\int_0^1$’ intégrale de 0 à 1
86 Annoter un graphique avec la fonction text()

Cas d’usage courants

AƯicher des statistiques dans le graphique

[Link](42)
donnees = [Link](100, 15, 500
moyenne = [Link]()
ecart_type = [Link]()
taille = len(donnees)
[Link](donnees, bins=30, edgecolor=’black’, alpha=0.7
[Link](moyenne, color=’red’, linestyle=’--’, linewidth=2
resume = (f’n = {taille}\n’
f’Moyenne = {moyenne:.2f}\n’
f’Ecart-type = {ecart_type:.2f}’)
[Link](0.95, 0.95, resume,
transform=[Link]().transAxes,
ha=’right’, va=’top’,
fontsize=11,
bbox={‘facecolor’: ‘white’,
‘edgecolor’: ‘gray’,
‘boxstyle’: ‘round,pad=0.5’})
[Link](‘Valeur’)
[Link](‘Effectif’)
[Link]()

Étiqueter individuellement des points

villes = [‘Paris’, ‘Lyon’, ‘Marseille’, ‘Toulouse’, ‘Nice’]


pib_par_habitant = [55, 45, 40, 42, 43
esperance_vie = [82.5, 83.1, 81.8, 82.9, 83.5
[Link](figsize=(9, 6
[Link](pib_par_habitant, esperance_vie, s=100, color=’steelblue’, edgecolors=’black’)
# Etiqueter chaque point
for indice in range(len(villes)):
[Link](pib_par_habitant[indice] + 0.3,
esperance_vie[indice],
Annoter un graphique avec la fonction text() 87
villes[indice],
fontsize=10,
va=’center’)
[Link](‘PIB par habitant (k EUR’
[Link](‘Esperance de vie (annees)’)
[Link](True, alpha=0.3
[Link]()
9.3 Annoter un point remarquable sur une courbe
x = [Link](0, 2 * [Link], 100
y = [Link](x)
# Recherche du maximum
indice_max = [Link](y)
x_max = x[indice_max]
y_max = y[indice_max]
[Link](x, y)
[Link](x_max, y_max, ‘ro’, markersize=10
[Link](x_max, y_max + 0.1,
f’Maximum\n({x_max:.2f}, {y_max:.2f})’,
ha=’center’, va=’bottom’,
fontsize=10,
bbox={‘facecolor’: ‘lightyellow’,
‘edgecolor’: ‘orange’,
‘boxstyle’: ‘round’})
[Link]()

Ajouter une source ou une date

[Link](x, y)
[Link](‘Evolution mensuelle’)
# Source discretement en bas a droite
[Link](0.99, 0.01,
‘Source : INSEE, 2025’,
transform=[Link]().transAxes,
ha=’right’, va=’bottom’,
fontsize=8,
fontstyle=’italic’,
color=’gray’)
88 Annoter un graphique avec la fonction text()

[Link]()

Distinction avec annotate()

Matplotlib propose une fonction annotate() qui est une extension de text(). Elle ajoute un point
d’ancrage et éventuellement une flèche pointant vers un élément du graphique.

[Link](x, y)
# annotate() : texte + fleche
[Link](
‘Maximum’,
xy=(x_max, y_max), # point pointe
xytext=(x_max - 1, y_max), # position du texte
fontsize=12,
arrowprops={‘arrowstyle’: ‘→,’ ‘color’: ‘red’})
[Link]()

Le choix entre les deux fonctions dépend du besoin :


• text() : texte libre, sans lien explicite avec un élément du graphique (statistiques, sources,
titres internes, formules).
• annotate() : texte désignant un élément précis, avec possibilité d’ajouter une flèche qui
relie visuellement le texte à l’élément commenté.

Bonnes pratiques

• Utiliser transform=[Link]().transAxes pour les annotations fixes : les statistiques, sources


ou titres internes doivent rester au même endroit quelles que soient les échelles des
données.
• Maîtriser les alignements ha et va : un texte correctement ancré reste bien positionné
même si la figure est redimensionnée. Sans ancrage explicite, le texte peut déborder.
• Pré-formater les nombres avec des f-strings : f’{valeur:.2f}’ pour 2 décimales, f’{valeur:,.0f}’
pour un séparateur de milliers, f’{valeur:.1%}’ pour un pourcentage.
• Utiliser bbox avec parcimonie : un cadre attire l’œil et doit être réservé aux informations
vraiment importantes (résumé statistique, maximum d’une courbe). Trop de cadres
rendent la figure chargée.
• Préférer le préfixe r (raw string) pour toute chaîne contenant des commandes LaTeX. Sans
ce préfixe, Python interprète les backslash comme des échappements.
• Choisir annotate() plutôt que text() dès qu’il s’agit de désigner un point précis du graphique.
La flèche explicite la relation entre le texte et l’élément annoté.
Annoter un graphique avec la fonction text() 89
• Limiter le nombre d’annotations : au-delà de quelques textes, la figure devient illisible.
Si beaucoup d’éléments doivent être commentés, envisager une légende ou un tableau
séparé.
• Garder une taille de police cohérente : dans une même figure, utiliser 2 ou 3 tailles
maximum (titre, annotations principales, annotations secondaires).

Conclusion

La fonction text() est l’outil fondamental d’annotation libre dans Matplotlib. Sa richesse
paramétrique (fontsize, color, rotation, bbox, transform, etc) lui permet de répondre à des
besoins très variés : ajouter un commentaire, a icher des statistiques, étiqueter des points,
insérer une formule mathématique. Sa maîtrise passe par la compréhension de trois notions
clés : le système de coordonnées (données vs axes), l’alignement autour du point d’ancrage,
et la mise en forme typographique.
Au-delà de text(), l’écosystème Matplotlib propose plusieurs variantes complémentaires :
• annotate() pour les annotations avec flèche.
• figtext() pour placer du texte au niveau de la figure plutôt que d’un axe particulier.
• La méthode suptitle() déjà évoquée pour les titres d’ensemble.
Ensemble, ces fonctions donnent à l’utilisateur de Matplotlib toute la liberté nécessaire pour
enrichir ses graphiques de commentaires informatifs et esthétiques.
Afficher des images et des tableaux 2D
avec la fonction imshow() F10
La fonction imshow() (abréviation de image show) permet d’a icher un tableau bidimensionnel
de valeurs sous forme d’image. Chaque valeur du tableau correspond à un pixel, dont
l’intensité ou la couleur reflète la valeur numérique. Cette fonction répond à deux besoins
distincts mais complémentaires :
• A icher une image au sens classique du terme (photo, radiographie, capture d’écran),
représentée par un tableau de valeurs de pixels.
• Visualiser des données matricielles (matrice de corrélation, carte de chaleur, résultat de
convolution, champ scalaire 2D, etc) pour en comprendre la structure spatiale.
Ce second usage, appelé carte de chaleur (heatmap), est probablement le plus fréquent en
science des données. Il est particulièrement puissant pour repérer des motifs, des zones de
concentration ou des ruptures dans un tableau de chi res.

Importation des bibliothèques

import [Link] as plt


import numpy as np
92 Afficher des images et des tableaux 2D avec la fonction imshow()

Syntaxe générale

La signature simplifiée de la fonction est [Link](X, cmap=None, vmin=None, vmax=None,


interpolation=None, aspect=’equal’, origin=’upper’, extent=None, **kwargs). Les paramètres
principaux sont :
• X : tableau 2D (nuances de gris) ou 3D (RGB/RGBA) à a icher.
• cmap : carte de couleurs appliquée aux tableaux 2D.
• vmin, vmax : bornes de l’échelle de couleurs.
• interpolation : méthode de lissage entre pixels.
• aspect : rapport d’aspect des pixels (‘equal’, ‘auto’ ou un nombre).
• origin : position du pixel (0, 0) (‘upper’ ou ‘lower’).
• extent : bornes des axes en coordonnées réelles, sous forme (xmin, xmax, ymin, ymax).
Formats de tableau acceptés :
• 2D (M x N) : valeurs scalaires, interprétées selon la cmap. C’est le cas des cartes de
chaleur.
• 3D (M x N x 3) : image couleur RGB, chaque pixel étant défini par trois canaux.
• 3D (M x N x 4) : image couleur RGBA, avec un canal alpha pour la transparence.

Premier exemple

A icher un tableau 2D aléatoire comme heatmap.

import [Link] as plt


import numpy as np
[Link](0)
matrice = [Link](10, 10
# construction
[Link](matrice)
[Link]()
# affichage
[Link]()

Deux points importants à observer :


• Par défaut, Matplotlib utilise la carte de couleurs ‘viridis’ (du violet au jaune).
• L’appel à [Link]() ajoute une échelle indiquant la correspondance entre couleurs
et valeurs. Elle est quasi indispensable pour toute heatmap, car sans elle les couleurs
restent ininterprétables.
Afficher des images et des tableaux 2D avec la fonction imshow() 93

Sens des axes et paramètre origin

Par convention, imshow() suit la convention image : le pixel (0, 0) est en haut à gauche, et l’axe
des Y augmente vers le bas. C’est l’inverse des conventions mathématiques habituelles. Ce
comportement est contrôlé par le paramètre origin.

Valeur Position du pixel (0, 0)

‘upper’ (défaut) en haut à gauche, axe y vers le bas (convention image)

‘lower’ en bas à gauche, axe y vers le haut (convention mathématique)

matrice = [Link](16).reshape(4, 4)
[Link](figsize=(10, 4
[Link](1, 2, 1
[Link](matrice, origin=’upper’)
[Link]("origin=’upper’")
[Link]()
[Link](1, 2, 2
[Link](matrice, origin=’lower’)
[Link]("origin=’lower’")
[Link]()
plt.tight_layout()
[Link]()

Règle pratique : utiliser origin=’upper’ (défaut) pour a icher des images réelles, et origin=’lower’
pour visualiser des données mathématiques (fonctions 2D, champs scalaires), afin de
retrouver l’orientation habituelle des graphiques.

Cartes de couleurs (cmap)

Le choix de la cmap est déterminant pour l’interprétabilité d’une heatmap. Matplotlib classe
les cartes en plusieurs familles selon la nature des données.

Cartes séquentielles
Adaptées aux données ordonnées du bas vers le haut (ex. températures, concentrations,
probabilités). Les principales sont les suivantes.
94 Afficher des images et des tableaux 2D avec la fonction imshow()

[Link](matrice, cmap=’viridis’) # defaut, recommande


[Link](matrice, cmap=’plasma’)
[Link](matrice, cmap=’inferno’)
[Link](matrice, cmap=’magma’)
[Link](matrice, cmap=’cividis’) # optimisee pour daltoniens
[Link](matrice, cmap=’Blues’)
[Link](matrice, cmap=’gray’) # nuances de gris

Cartes divergentes
Adaptées aux données centrées autour d’une valeur de référence (souvent zéro), où l’on veut
distinguer les valeurs négatives des positives.

matrice = [Link](10, 10 # valeurs centrees sur 0


[Link](matrice, cmap=’coolwarm’) # bleu → rouge
[Link](matrice, cmap=’RdBu_r’) # rouge → bleu inverse
[Link](matrice, cmap=’seismic’)
[Link]()
[Link]()

Astuce : ajouter _r au nom d’une cmap inverse son sens (‘viridis_r’, ‘Blues_r’, etc).

Cartes à éviter
Les cartes ‘jet’ et ‘rainbow’, longtemps populaires, sont aujourd’hui déconseillées : elles créent
des artefacts visuels (fausses limites, accentuation de certaines zones), et sont inaccessibles
aux personnes daltoniennes. Il vaut mieux privilégier ‘viridis’ ou ‘cividis’.

Bornes de l’échelle (vmin et vmax)

Par défaut, Matplotlib utilise le minimum et le maximum du tableau pour définir l’échelle de
couleurs. Cela peut poser problème quand :
• Quelques valeurs aberrantes écrasent l’essentiel de la dynamique visuelle.
• On veut comparer plusieurs cartes de chaleur avec une échelle commune.
Les paramètres vmin et vmax permettent de forcer les bornes par [Link](matrice,
cmap=’viridis’, vmin=0, vmax=1) avant l’a ichage [Link]().
Les valeurs en dehors de [vmin, vmax] sont écrêtées (saturent aux extrémités de la carte de
couleurs). C’est utile pour mettre en évidence la plage d’intérêt sans se laisser perturber par
Afficher des images et des tableaux 2D avec la fonction imshow() 95
des valeurs aberrantes (outliers).

Interpolation entre pixels

Le paramètre interpolation contrôle la manière dont les pixels sont rendus. Les options les
plus utiles sont les suivantes.

Valeur EƯet

‘none’ pixels nets, sans lissage (recommandé pour les heatmaps)

‘nearest’ pixellisé, équivalent visuel à ‘none’ dans la plupart des cas

‘bilinear’ lissage linéaire entre pixels voisins

‘bicubic’ lissage cubique, rendu très doux (adapté aux photos)

‘gaussian’ lissage gaussien, rendu flou

Règle pratique : pour une heatmap de données, interpolation=’none’ est quasi systématiquement
le bon choix. Chaque pixel correspond à une donnée distincte, et le lissage tromperait le
lecteur en suggérant une continuité fictive. Le lissage est réservé aux photos ou aux données
spatialement continues (champs physiques échantillonnés).

Coordonnées réelles (extent)

Par défaut, les axes a ichent les indices des pixels (de 0 à N-1). Dans bien des cas, on souhaite
que les axes indiquent des coordonnées physiques (temps, distance, longueur d’onde, etc).
Le paramètre extent prend un tuple (xmin, xmax, ymin, ymax).

# Fonction 2D  f(x, y) = sin(x) * cos(y)


abscisses = [Link](-[Link], [Link], 200
ordonnees = [Link](-[Link], [Link], 200
X, Y  [Link](abscisses, ordonnees)
Z  [Link](X) * [Link](Y)
[Link](Z,
extent=[-[Link], [Link], -[Link], [Link]],
origin=’lower’,
cmap=’RdBu_r’)
96 Afficher des images et des tableaux 2D avec la fonction imshow()

[Link](label=’f(x, y)’)
[Link](‘x’)
[Link](‘y’)
[Link](‘Fonction sin(x)·cos(y)’)
[Link]()

On remarque la combinaison typique : extent pour calibrer les axes, origin=’lower’ pour
retrouver l’orientation mathématique, et une carte divergente car la fonction a des valeurs
positives et négatives.

Rapport d’aspect (aspect)

Le paramètre aspect contrôle la forme des pixels :


• ‘equal’ (par défaut) : pixels carrés, forme fidèle de l’image.
• ‘auto’ : pixels étirés pour remplir la zone graphique.
• Un nombre : ratio hauteur/largeur personnalisé.

# Matrice tres allongee : 5 lignes x 50 colonnes


matrice_large = [Link](5, 50
[Link](figsize=(10, 4
[Link](2, 1, 1
[Link](matrice_large, aspect=’equal’)
[Link]("aspect=’equal’ (pixels carres)")
[Link](2, 1, 2
[Link](matrice_large, aspect=’auto’)
[Link]("aspect=’auto’ (remplit la zone)")
plt.tight_layout()
[Link]()

Pour une image photographique, ‘equal’ est indispensable (sinon l’image est déformée). Pour
une heatmap très allongée, ‘auto’ est souvent plus lisible.

Annoter une heatmap

Une pratique courante est d’écrire la valeur numérique dans chaque cellule, en combinant
imshow() et text().

matrice = [Link]([[0.23, 0.45, 0.67, 0.81, 0.12, 0.56, 0.34, 0.89, 0.41
Afficher des images et des tableaux 2D avec la fonction imshow() 97
lignes = [‘Lun’, ‘Mar’, ‘Mer’]
colonnes = [‘Matin’, ‘Midi’, ‘Soir’]
[Link](figsize=(6, 5
[Link](matrice, cmap=’YlOrRd’)
[Link](label=’Valeur’)
# Etiquettes des axes
[Link](range(len(colonnes)), colonnes)
[Link](range(len(lignes)), lignes)
# Texte dans chaque cellule
nb_lignes, nb_colonnes = [Link]
for ligne in range(nb_lignes):
for colonne in range(nb_colonnes):
[Link](colonne, ligne,
f’{matrice[ligne, colonne]:.2f}’,
ha=’center’, va=’center’,
color=’black’)
[Link](‘Heatmap annotee’)
[Link]()

Astuce : pour assurer la lisibilité du texte quelle que soit la couleur de fond, on peut adapter
dynamiquement la couleur de la police (noir sur fond clair, blanc sur fond sombre).

for ligne in range(nb_lignes):


for colonne in range(nb_colonnes):
valeur = matrice[ligne, colonne]
couleur_texte = ‘white’ if valeur > 0.5 else ‘black’
[Link](colonne, ligne, f’{valeur:.2f}’,
ha=’center’, va=’center’,
color=couleur_texte)

Cas d’usage courants

Matrice de corrélation
Un usage typique en science des données est de visualiser la corrélation entre les colonnes
d’un tableau.

[Link](1)
98 Afficher des images et des tableaux 2D avec la fonction imshow()

# Generation de donnees fictives a 4 variables


nb_observations = 100
donnees = [Link](nb_observations, 4
donnees[:, 1] = donnees[:, 0] * 0.8  [Link](nb_observations) * 0.2
donnees[:, 3] = -donnees[:, 2] * 0.5  [Link](nb_observations) * 0.5
noms_variables = [‘A’, ‘B’, ‘C’, ‘D’]
matrice_correlation = [Link](donnees, rowvar=False)
[Link](figsize=(6, 5
[Link](matrice_correlation, cmap=’RdBu_r’, vmin=-1, vmax=1
[Link](label=’Correlation’)
[Link](range(4), noms_variables)
[Link](range(4), noms_variables)
for ligne in range(4):
for colonne in range(4):
[Link](colonne, ligne,
f’{matrice_correlation[ligne, colonne]:.2f}’,
ha=’center’, va=’center’,
color=’black’, fontsize=10
[Link](‘Matrice de correlation’)
# affichage
[Link]()

AƯicher une image en niveaux de gris

# Creation d’une image factice : degrade diagonal


taille = 100
image = [Link]((taille, taille))
for ligne in range(taille):
for colonne in range(taille):
image[ligne, colonne] = (ligne + colonne) / (2 * taille)
[Link](image, cmap=’gray’)
[Link](‘off’) # masque les axes, comme pour une photo
[Link](‘Image en niveaux de gris’)
# affichage
[Link]()
Afficher des images et des tableaux 2D avec la fonction imshow() 99

Visualiser une fonction mathématique 2D

abscisses = [Link](-3, 3, 300


ordonnees = [Link](-3, 3, 300
X, Y  [Link](abscisses, ordonnees)
Z  [Link](-(X**2  Y**2 # cloche gaussienne
[Link](Z,
extent=[-3, 3, 3, 3,
origin=’lower’,
cmap=’inferno’)
[Link](label=’f(x, y)’)
[Link](‘x’)
[Link](‘y’)
[Link](r’Gaussienne $f(x,y) = e^{-(x^2+y^2$’)
[Link]()

Image couleur (tableau RGB)

# Creation d’une image couleur 1001003


image_couleur = [Link]((100, 100, 3
image_couleur[:, :, 0  [Link](0, 1, 100 # rouge horizontal
image_couleur[:, :, 1  [Link](0, 1, 100.reshape(-1, 1 # vert vertical
image_couleur[:, :, 2  0.5 # bleu constant
[Link](image_couleur)
[Link](‘off’)
[Link](‘Image RGB synthetique’)
[Link]()

Important - Pour un tableau 3D RGB, les valeurs doivent être :


• Soit des flottants entre 0 et 1.
• Soit des entiers entre 0 et 255 (type uint8).
Des valeurs hors de ces plages produisent des avertissements et un rendu imprévisible.

Bonnes pratiques
• Toujours ajouter une colorbar() pour les heatmaps : sans échelle, les couleurs sont
ininterprétables.
100 Afficher des images et des tableaux 2D avec la fonction imshow()

• Choisir la cmap selon la nature des données : séquentielle pour des valeurs ordonnées,
divergente pour des valeurs centrées autour d’une référence.
• Utiliser origin=’lower’ pour les données mathématiques : cela rétablit l’orientation
habituelle des axes (Y vers le haut). Garder ‘upper’ pour les images réelles.
• Spécifier interpolation=’none’ pour les heatmaps de données : le lissage fait croire à une
continuité qui n’existe pas.
• Fixer vmin et vmax quand on compare plusieurs heatmaps entre elles, pour une échelle
commune cohérente.
• Utiliser extent dès que les axes représentent autre chose que des indices de pixels.
• Éviter ‘jet’ et ‘rainbow’ : préférer ‘viridis’ ou ‘cividis’, perceptivement uniformes et
accessibles aux daltoniens.
• Annoter les cellules quand la heatmap est petite (moins de 10x10) : les valeurs chi rées
complètent utilement le code couleur.

Conclusion

La fonction imshow() est l’outil universel pour a icher des tableaux 2D comme des images
ou des heatmaps dans Matplotlib. Sa puissance tient à sa polyvalence : on peut aussi bien
l’utiliser pour visualiser une photo, une matrice de corrélation, le résultat d’une simulation
numérique, une image médicale ou une sortie de réseau de neurones. Sa maîtrise repose
sur quelques concepts clés : le choix de la carte de couleurs adaptée au type de données, la
bonne orientation des axes via origin, et le calibrage éventuel des coordonnées physiques via
extent.
Pour des besoins plus spécialisés, Matplotlib propose plusieurs fonctions voisines :
• [Link]() pour les grilles non régulières.
• [Link]() et [Link]() pour les courbes ou zones de niveau.
• [Link]() qui est un raccourci spécifique aux matrices numériques (avec des réglages
par défaut mieux adaptés).
Pour l’a ichage d’images au sens photographique, on combine souvent imshow() avec la
bibliothèque PIL ou opencv-python, qui facilitent le chargement et le traitement préalable
des fichiers image.
Lister toutes les fonctions intégrées
de Matplotlib F11
Matplotlib est une bibliothèque graphique aux multiples facettes. L’objectif de ce notebook
est de permettre de lister précisément toutes les fonctions graphiques intégrées disponibles
dans le module [Link]. On va principalement :
• Extraire la liste complète des fonctions de pyplot.
• Filtrer celles qui produisent un graphique.
• Les classer par catégorie (1D, 2D, 3D, statistiques, etc).
• A icher leur signature et une brève description.
Tout le code source de programmation de cette fiche se trouve dans le fichier f11_matplotlib_
fonctions_graphiques.ipynb placé dans le dossier NotebookJupyter de l’archive téléchargée.

Importation des bibliothèques


import matplotlib
import [Link] as plt
import inspect
import pandas as pd
print(f"Version de matplotlib : {matplotlib.__version__}")

Version de matplotlib : 3.10.6


102 Lister toutes les fonctions intégrées de Matplotlib

Extraction de toutes les fonctions de pyplot

On récupère tous les attributs de [Link] qui sont des fonctions. Avec la version
utilisée de Matplotlib, qui est la 3.10.6, on dénombre 171 fonctions intégrées.

def lister_fonctions_pyplot():
"""Retourne la liste complète des fonctions publiques de [Link]."""
toutes_fonctions = []
for nom in dir(plt):
if [Link]("_"):
continue
objet = getattr(plt, nom)
if [Link](objet) or [Link](objet):
toutes_fonctions.append(nom)
return sorted(toutes_fonctions)
# test
liste_complete = lister_fonctions_pyplot()
print(f"Nombre total de fonctions dans pyplot : {len(liste_complete)}")
print("Extrait des 20 premières :")
for nom_fonction in liste_complete[:20]:
print(f" - {nom_fonction}")

Nombre total de fonctions dans pyplot : 171


Extrait des 20 premières :
- acorr
- angle_spectrum
- annotate
- arrow
- autoscale
- autumn
- axes
- axhline
- axhspan
- axis
- axline
- axvline
- axvspan
Lister toutes les fonctions intégrées de Matplotlib 103
- bar
- bar_label
- barbs
- barh
- bone
- box
- boxplot

Filtrage des fonctions strictement graphiques

Toutes les fonctions de pyplot ne produisent pas forcément un tracé comme par exemple
show(), savefig(), subplot(), xlabel(), etc. Matplotlib expose une liste o icielle des fonctions de
tracé dans [Link]. On va utiliser cette source pour obtenir une liste fiable.

from [Link] import Axes


def extraire_fonctions_tracage():
"""
Extrait les méthodes de tracage de la classe Axes.
Ces méthodes sont aussi accessibles via pyplot.
"""
# Liste des mots-cles typiques des fonctions de trace
mots_cles_graphiques = {
"plot", "scatter", "bar", "hist", "pie", "boxplot", "violinplot",
"errorbar", "fill", "stem", "step", "stackplot", "pcolor", "contour",
"imshow", "matshow", "quiver", "streamplot", "hexbin", "hlines",
"vlines", "axhline", "axvline", "axhspan", "axvspan", "arrow",
"annotate", "text", "table", "spy", "tricontour", "triplot",
"eventplot", "broken_barh", "acorr", "xcorr", "angle_spectrum",
"magnitude_spectrum", "phase_spectrum", "psd", "csd", "cohere",
"specgram", "loglog", "semilogx", "semilogy", "polar"
}
fonctions_trouvees = []
for nom in dir(plt):
if [Link]("_"):
continue
if nom in mots_cles_graphiques or any(mc in nom for mc in ["plot", "bar", "hist"]):
objet = getattr(plt, nom)
104 Lister toutes les fonctions intégrées de Matplotlib

if callable(objet):
fonctions_trouvees.append(nom)
return sorted(set(fonctions_trouvees))
# test
fonctions_graphiques = extraire_fonctions_tracage()
print(f"Nombre de fonctions graphiques identifiées : {len(fonctions_graphiques)}")
for nom in fonctions_graphiques:
print(f" - {nom}")

Nombre de fonctions graphiques identifiées : 62


- Subplot
- SubplotSpec
- acorr
- angle_spectrum
- annotate
- arrow
- axhline
- axhspan
- axvline
- axvspan
- bar
- bar_label
- barbs
- barh
- boxplot
- broken_barh
- cohere
- colorbar
- contour
- csd
- errorbar
- eventplot
- fill
- get_plot_commands
- hexbin
- hist
- hist2d
- hlines
- imshow
Lister toutes les fonctions intégrées de Matplotlib 105
- loglog
- magnitude_spectrum
- matshow
- pcolor
- phase_spectrum
- pie
- plot
- plot_date
- polar
- psd
- quiver
- scatter
- semilogx
- semilogy
- specgram
- spy
- stackplot
- stem
- step
- streamplot
- subplot
- subplot2grid
- subplot_mosaic
- subplot_tool
- subplots
- subplots_adjust
- table
- text
- tricontour
- triplot
- violinplot
- vlines
- xcorr

Classement par catégorie

On regroupe les fonctions graphiques intégrées par type de visualisation.

categories_graphiques = {
106 Lister toutes les fonctions intégrées de Matplotlib

"Courbes et lignes 1D": [


"plot", "loglog", "semilogx", "semilogy", "step", "stem",
"fill_between", "fill_betweenx", "polar"
],
"Nuages de points et barres": [
"scatter", "bar", "barh", "bar_label", "broken_barh", "stackplot",
"hlines", "vlines", "eventplot"
],
"Statistiques et distributions": [
"hist", "hist2d", "boxplot", "violinplot", "errorbar", "pie",
"hexbin"
],
"Images, matrices et champs 2D": [
"imshow", "matshow", "pcolor", "pcolormesh", "contour", "contourf",
"spy"
],
"Champs vectoriels": [
"quiver", "quiverkey", "streamplot", "barbs"
],
"Maillages triangulaires": [
"tricontour", "tricontourf", "tripcolor", "triplot"
],
"Analyse du signal": [
"acorr", "xcorr", "angle_spectrum", "magnitude_spectrum",
"phase_spectrum", "psd", "csd", "cohere", "specgram"
],
"Annotations et lignes de repere": [
"axhline", "axvline", "axhspan", "axvspan", "axline", "arrow",
"annotate", "text", "table"
]
}
def afficher_classement(dictionnaire_categories):
"""Affiche les fonctions graphiques classées par catégorie."""
total = 0
for categorie, liste_fonctions in dictionnaire_categories.items():
print(f"=== {categorie} ({len(liste_fonctions)} fonctions) ===")
for nom in liste_fonctions:
Lister toutes les fonctions intégrées de Matplotlib 107
disponible = "✓" if hasattr(plt, nom) else "✗"
print(f" [{disponible}] plt.{nom}")
total += len(liste_fonctions)
print(f"Total : {total} fonctions graphiques répertoriées.")
# test
afficher_classement(categories_graphiques)

=== Courbes et lignes 1D (9 fonctions) ===


[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] plt.fill_between
[✓] plt.fill_betweenx
[✓] [Link]
=== Nuages de points et barres (9 fonctions) ===
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] plt.bar_label
[✓] plt.broken_barh
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
=== Statistiques et distributions (7 fonctions) ===
[✓] [Link]
[✓] plt.hist2d
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
=== Images, matrices et champs 2D (7 fonctions) ===
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
108 Lister toutes les fonctions intégrées de Matplotlib

[✓] [Link]
[✓] [Link]
[✓] [Link]
=== Champs vectoriels (4 fonctions) ===
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
=== Maillages triangulaires (4 fonctions) ===
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
=== Analyse du signal (9 fonctions) ===
[✓] [Link]
[✓] [Link]
[✓] plt.angle_spectrum
[✓] plt.magnitude_spectrum
[✓] plt.phase_spectrum
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
=== Annotations et lignes de repere (9 fonctions) ===
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
[✓] [Link]
Total : 58 fonctions graphiques répertoriées.

Tableau récapitulatif avec signatures et descriptions

On construit un DataFrame de Pandas qui contient le nom de la fonction, sa catégorie, sa


signature et la première ligne de sa docstring.
Lister toutes les fonctions intégrées de Matplotlib 109

def extraire_signature(nom_fonction):
"""Retourne la signature d’une fonction de pyplot sous forme de chaine."""
try:
objet = getattr(plt, nom_fonction)
signature = [Link](objet)
return f"{nom_fonction}{signature}"
except (ValueError, TypeError):
return f"{nom_fonction}(...)"
def extraire_description(nom_fonction):
"""Retourne la première ligne utile de la docstring."""
objet = getattr(plt, nom_fonction, None)
if objet is None or objet.__doc__ is None:
return "(pas de description)"
lignes = [[Link]() for ligne in objet.__doc__.split("\n") if [Link]()]
return lignes[0] if lignes else "(pas de description)"
def construire_tableau_recapitulatif(dictionnaire_categories):
"""Construit un DataFrame recapitulatif des fonctions graphiques."""
lignes = []
for categorie, liste_fonctions in dictionnaire_categories.items():
for nom in liste_fonctions:
if hasattr(plt, nom):
[Link]({
"Fonction": f"plt.{nom}",
"Categorie": categorie,
"Signature": extraire_signature(nom),
"Description": extraire_description(nom)
})
return [Link](lignes)
# test
tableau_recapitulatif = construire_tableau_recapitulatif(categories_graphiques)
pd.set_option("display.max_colwidth", 100
print(len(tableau_recapitulatif),"fonctions répertoriées")
print(tableau_recapitulatif.head())

58 fonctions répertoriées
Fonction Categorie \
110 Lister toutes les fonctions intégrées de Matplotlib

0 [Link] Courbes et lignes 1D


1 [Link] Courbes et lignes 1D
2 [Link] Courbes et lignes 1D
3 [Link] Courbes et lignes 1D
4 [Link] Courbes et lignes 1D

Signature \
0 plot(*args: ‘float | ArrayLike | str’, scalex: ‘bool’ = True, scaley: ‘bool’ =
True, data=None, ...
1 loglog(*args,
**kwargs) -> ‘list[Line2D]’
2 semilogx(*args,
**kwargs) -> ‘list[Line2D]’
3 semilogy(*args,
**kwargs) -> ‘list[Line2D]’
4 step(x: ‘ArrayLike’, y: ‘ArrayLike’, *args, where: "Literal[‘pre’, ‘post’,
‘mid’]" = ‘pre’, data...

Description
0 Plot y versus x as lines and/or markers.
1 Make a plot with log scaling on both the x- and y-axis.
2 Make a plot with log scaling on the x-axis.
3 Make a plot with log scaling on the y-axis.
4 Make a step plot.

Recherche d’une fonction spécifique

On compose une petite fonction utilitaire pour chercher une fonction par mot-clé.

def rechercher_fonction(mot_cle, tableau):


"""Recherche dans le tableau recapitulatif les fonctions contenant le mot-cle."""
masque = (
tableau["Fonction"].[Link](mot_cle, case=False, na=False)
| tableau["Description"].[Link](mot_cle, case=False, na=False)
)
return tableau[masque]
# Exemple : chercher tout ce qui concerne les histogrammes
print(rechercher_fonction("hist", tableau_recapitulatif))
Lister toutes les fonctions intégrées de Matplotlib 111
Fonction Categorie \
18 [Link] Statistiques et distributions
19 plt.hist2d Statistiques et distributions

Signature \
18 hist(x: ‘ArrayLike | Sequence[ArrayLike]’, bins: ‘int | Sequence[float] | str |
None’ = None, *,...
19 hist2d(x: ‘ArrayLike’, y: ‘ArrayLike’, bins: ‘None | int | tuple[int, int] |
ArrayLike | tuple[A...

Description
18 Compute and plot a histogram.
19 Make a 2D histogram plot.

# Exemple : chercher tout ce qui concerne les contours


print(rechercher_fonction("contour", tableau_recapitulatif))

Fonction Categorie \
29 [Link] Images, matrices et champs 2D
30 [Link] Images, matrices et champs 2D
36 [Link] Maillages triangulaires
37 [Link] Maillages triangulaires

Signature \
29 contour(*args, data=None, **kwargs) -> ‘QuadContourSet’
30 contourf(*args, data=None, **kwargs) -> ‘QuadContourSet’
36 tricontour(*args, **kwargs)
37 tricontourf(*args, **kwargs)

Description
29 Plot contour lines.
30 Plot filled contours.
36 Draw contour lines on an unstructured triangular grid.
37 Draw contour regions on an unstructured triangular grid.

Exporter la liste complète

On peut sauvegarder le tableau dans un fichier au format CSV et dans une feuille d’un classeur
EXCEL, au format xlsx (figure 1), pour une consultation ultérieure.
112 Lister toutes les fonctions intégrées de Matplotlib

Figure n°1

def sauvegarder_tableau_csv(tableau, chemin_fichier="f11/fonctions_graphiques_matplotlib.csv"):


"""Sauvegarde le tableau recapitulatif dans un fichier CSV."""
tableau.to_csv(chemin_fichier, index=False, encoding="utf-8")
print(f"Tableau sauvegardé dans : {chemin_fichier}")
print(f"Nombre de lignes : {len(tableau)}")
def sauvegarder_tableau_excel(tableau, chemin_fichier="f11/fonctions_graphiques_matplotlib.xlsx"):
"""Sauvegarde le tableau recapitulatif dans un fichier EXCEL."""
tableau.to_excel(chemin_fichier,sheet_name="fonctions",index_label=True,index=False)
print(f"Tableau sauvegardé dans : {chemin_fichier}")
print(f"Nombre de lignes : {len(tableau)}")
# test
sauvegarder_tableau_csv(tableau_recapitulatif)
sauvegarder_tableau_excel(tableau_recapitulatif)

Tableau sauvegardé dans : f11/fonctions_graphiques_matplotlib.csv


Nombre de lignes : 58
Tableau sauvegardé dans : f11/fonctions_graphiques_matplotlib.xlsx
Nombre de lignes : 58
Lister toutes les fonctions intégrées de Matplotlib 113

Résumé final

Pour résumer tout ce que l’on vient de voir en programmation, on compose un résumé au
format texte pour pouvoir apprécier l’étendue des fonctions intégrées de Matplotlib.

def afficher_resume(tableau):
"""Affiche un resume statistique du tableau des fonctions graphiques."""
print("=" * 60
print("RESUME DES FONCTIONS GRAPHIQUES MATPLOTLIB")
print("=" * 60
print(f"Version matplotlib : {matplotlib.__version__}")
print(f"Nombre total de fonctions graphiques : {len(tableau)}")
print(f"Repartition par categorie :")
repartition = tableau["Categorie"].value_counts()
for nom_categorie, nombre in [Link]():
print(f" - {nom_categorie} : {nombre}")
print("=" * 60
# test
afficher_resume(tableau_recapitulatif)

============================================================
RESUME DES FONCTIONS GRAPHIQUES MATPLOTLIB
============================================================
Version matplotlib : 3.10.6
Nombre total de fonctions graphiques : 58
Repartition par categorie :
- Courbes et lignes 1D : 9
- Nuages de points et barres : 9
- Analyse du signal : 9
- Annotations et lignes de repere : 9
- Statistiques et distributions : 7
- Images, matrices et champs 2D : 7
- Champs vectoriels : 4
- Maillages triangulaires : 4
============================================================
Visualiser
les couleurs prédéfinies de Matplolib F12
Dans cette fiche, on compose un notebook qui a iche toutes les couleurs nommées
disponibles de Matplotlib sous forme de tableaux visuels. Matplotlib propose plusieurs
familles de couleurs prédéfinies :
• Couleurs de base (b, g, r, c, m, y, k, w).
• Couleurs Tableau (tab:blue, tab:orange, etc).
• Couleurs CSS4 (148 couleurs nommées HTML/CSS).
• Couleurs XKCD (~950 couleurs issues du sondage XKCD).
Le module [Link] regroupe tout ce qui concerne la gestion des couleurs dans
Matplotlib : définition, conversion, normalisation et création de palettes personnalisées.
Pour chaque couleur, on a iche un rectangle coloré, son nom et son code hexadécimal
correspondant. Tout le code source de programmation de cette fiche se trouve dans le fichier
f12_matplotlib_couleurs_predefinies.ipynb placé dans le dossier NotebookJupyter de l’archive
téléchargée.

Importation des bibliothèques


import [Link] as plt
import [Link] as mcolors
import math
116 Visualiser les couleurs prédéfinies de Matplotlib

Contenu du module [Link]

Le module [Link] regroupe tout ce qui concerne la gestion des couleurs dans
Matplotlib : définition, conversion, normalisation et création de palettes personnalisées.

Les 4 grandes fonctionnalités

Dictionnaires de couleurs nommées :


• mcolors.BASE_COLORS : 8 couleurs de base (b, g, r, etc).
• mcolors.TABLEAU_COLORS : 10 couleurs de la palette Tableau.
• mcolors.CSS4_COLORS : 148 couleurs du standard HTML/CSS.
• mcolors.XKCD_COLORS : 949 couleurs du sondage XKCD.
Fonctions de conversion entre formats :
• mcolors.to_rgb("red") → (1.0, 0.0, 0.0) : vers tuple RGB.
• mcolors.to_rgba("red", alpha=0.5) → (1.0, 0.0, 0.0, 0.5) : vers RGBA avec transparence.
• mcolors.to_hex((1, 0, 0)) → "# 0000" : vers code hexadécimal.
• mcolors.rgb_to_hsv(...) et mcolors.hsv_to_rgb(...) : fonctions de conversions entre espaces
colorimétriques.
Classes pour créer des palettes de couleurs (colormaps) personnalisées :
• [Link]([...]) : palette à partir d’une liste de couleurs (qualitative/
discrète).
• [Link].from_list(...) : palette dégradée entre plusieurs
couleurs.
Classes de normalisation des valeurs - Elles contrôlent comment les données numériques
sont mappées sur [0, 1] avant d’appliquer une colormap :
• [Link](vmin, vmax) : normalisation linéaire standard.
• [Link](...) : échelle logarithmique (utile pour les grandes plages).
• [Link](vcenter=0) : normalisation divergente autour d’un centre.
• [Link](...) : découpage en classes discrètes.

Exemple synthétique

import [Link] as mcolors


# Conversion
code_hex = mcolors.to_hex("steelblue") # "#4682b4"
rgb = mcolors.to_rgb("#ff5733") # 1.0, 0.341, 0.2
# Palette personnalisee
ma_palette = [Link].from_list(
Visualiser les couleurs prédéfinies de Matplotlib 117
"ma_palette", ["navy", "white", "darkred"]
)
# Normalisation divergente autour de zero
norme = [Link](vmin=-10, vcenter=0, vmax=50

En résumé, [Link] est le moteur colorimétrique de Matplotlib, tandis que matplotlib.


pyplot est l’interface qui l’utilise pour tracer.

Fonction générique de visualisation

On construit une fonction a icher_tableau_couleurs() qui prend un dictionnaire {nom: code_


hex} et qui produit un tableau visuel.

def afficher_tableau_couleurs(dictionnaire_couleurs, titre, nombre_colonnes=4,


trier_par_teinte=True, hauteur_ligne=22,
largeur_rectangle=70, espacement_texte=12
"""
Affiche un tableau visuel des couleurs avec nom et code hexadecimal.
Parametres
----------
dictionnaire_couleurs : dict
Dictionnaire {nom_couleur: code_hex}.
titre : str
Titre du tableau.
nombre_colonnes : int
Nombre de colonnes dans le tableau.
trier_par_teinte : bool
Si True, trie les couleurs par teinte (HSV pour un rendu agreable.
"""
# Conversion en liste de tuples (nom, hex)
liste_couleurs = [(nom, mcolors.to_hex(valeur)) for nom, valeur in dictionnaire_couleurs.items()]
# Tri optionnel par teinte (Hue, Saturation, Value)
if trier_par_teinte:
def cle_tri(element):
nom, code_hex = element
rgb = mcolors.to_rgb(code_hex)
hsv = mcolors.rgb_to_hsv(rgb)
118 Visualiser les couleurs prédéfinies de Matplotlib

return (round(hsv[0 * 20, hsv[1], hsv[2])


liste_couleurs.sort(key=cle_tri)
else:
liste_couleurs.sort(key=lambda element: element[0])
nombre_couleurs = len(liste_couleurs)
nombre_lignes = [Link](nombre_couleurs / nombre_colonnes)
largeur_colonne = 260
largeur_totale = largeur_colonne * nombre_colonnes
hauteur_totale = hauteur_ligne * nombre_lignes + 40
figure, axe = [Link](
figsize=(largeur_totale / 72, hauteur_totale / 72,
facecolor=’whitesmoke’,
dpi=300
)
axe.set_xlim(0, largeur_totale)
axe.set_ylim(0, hauteur_totale)
axe.invert_yaxis()
axe.set_axis_off()
# Titre
[Link](largeur_totale / 2, 20, titre, fontsize=16, fontweight="bold",
ha="center", va="center", family="Roboto Condensed")
# Tracer chaque couleur
for index, (nom_couleur, code_hex) in enumerate(liste_couleurs):
colonne = index % nombre_colonnes
ligne = index // nombre_colonnes
position_x = colonne * largeur_colonne + 10
position_y = ligne * hauteur_ligne + 40
# Rectangle de couleur
axe.add_patch([Link](
(position_x, position_y),
largeur_rectangle,
hauteur_ligne - 4,
facecolor=code_hex,
edgecolor="black",
linewidth=0.5
))
# Nom et code hexadecimal
Visualiser les couleurs prédéfinies de Matplotlib 119
texte_complet = f"{nom_couleur} {code_hex.upper()}"
[Link](
position_x + largeur_rectangle + espacement_texte,
position_y + (hauteur_ligne - 4 / 2,
texte_complet,
fontsize=9,
va="center",
ha="left",
family="Roboto Condensed"
)
plt.tight_layout()
[Link]()
return figure

Cette fonction a iche un tableau visuel de couleurs (rectangle coloré + nom + code
hexadécimal) à partir d’un dictionnaire {nom: couleur}.

Préparation des données

liste_couleurs = [(nom, mcolors.to_hex(valeur)) for ...]

On convertit chaque couleur en code hexadécimal.

Tri optionnel par teinte

hsv = mcolors.rgb_to_hsv(rgb)
return (round(hsv[0 * 20, hsv[1], hsv[2])

On passe dans un espace HSV pour grouper les couleurs proches visuellement. Le
round(hsv[0] * 20) crée 20 paquets de teintes : à l’intérieur d’un paquet, on trie par saturation
puis luminosité (plus pâle au plus vif).

Calcul de la grille

nombre_lignes = [Link](nombre_couleurs / nombre_colonnes)

On découpe la zone en lignes et en colonnes selon le nombre de couleurs.


120 Visualiser les couleurs prédéfinies de Matplotlib

Création du canevas

figure, axe = [Link](figsize=..., facecolor=’whitesmoke’, dpi=300


axe.set_axis_off()
axe.invert_yaxis()

• Division par 72 = conversion pixels → pouces (72 DPI standard).


• invert_yaxis() : pour que l’axe Y aille de haut en bas comme en lecture.

Boucle d’aƯichage

Pour chaque couleur, à la position calculée :


• [Link](...) → trace le rectangle coloré.
• [Link](...) → a iche nom + code hexadécimal à côté.

Points techniques notables

Élément Rôle

dpi=300 Haute résolution pour impression/export

facecolor=’whitesmoke’ Fond gris très clair

family="Roboto Condensed" Police condensée pour gagner de la place

return figure Permet de sauvegarder ensuite avec [Link](...)

Logique générale

C’est un placement manuel en coordonnées absolues. On n’utilise pas la grille automatique


de Matplotlib (subplots()), mais on dessine directement rectangles et textes sur un axe unique
en calculant chaque position (position_x, position_y).

Couleurs de base

Les 8 couleurs historiques de Matplotlib, accessibles par une seule lettre (figure 1).
couleurs_base = mcolors.BASE_COLORS
Visualiser les couleurs prédéfinies de Matplotlib 121
print(f"Nombre de couleurs de base : {len(couleurs_base)}")
# Conversion en hex pour avoir des codes uniformes
couleurs_base_hex = {nom: mcolors.to_hex(valeur) for nom, valeur in couleurs_base.items()}
# graphique
gph = afficher_tableau_couleurs(
couleurs_base_hex,
titre="Couleurs de base (BASE_COLORS",
nombre_colonnes=2,
trier_par_teinte=False
)
[Link]("f12/couleurs_de_base.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Nombre de couleurs de base : 8

Figure n°1

Couleurs Tableau (palette par défaut)

Les 10 couleurs utilisées par défaut pour les tracés successifs (figure 2).

couleurs_tableau = mcolors.TABLEAU_COLORS
print(f"Nombre de couleurs Tableau : {len(couleurs_tableau)}")
# graphique
gph = afficher_tableau_couleurs(
couleurs_tableau,
titre="Couleurs Tableau (TABLEAU_COLORS",
nombre_colonnes=2,
trier_par_teinte=False
)
[Link]("f12/couleurs_de_tableau.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)
122 Visualiser les couleurs prédéfinies de Matplotlib

Nombre de couleurs Tableau : 10

Figure n°2

Couleurs CSS4

Les couleurs CSS4 sont l’ensemble des 148 couleurs nommées définies par le W3C dans
la spécification CSS Color Module Level 4, standard utilisé par tous les navigateurs web.
Chaque couleur possède un nom anglais explicite (tomato, steelblue, lightgoldenrodyellow)
associé à un code hexadécimal fixe.
Elles incluent les 16 couleurs HTML historiques (red, blue, black, etc), les couleurs X11 héritées
de l’environnement Unix (darkorange, mediumseagreen, etc), et les gris nommés (gainsboro,
dimgray, slategray).
Matplotlib les expose via mcolors.CSS4_COLORS, ce qui permet d’utiliser directement leur
nom dans n’importe quel tracé comme [Link](x, y, color="steelblue"). Le code ci-dessous
liste les 148 couleurs CSS4 nommées issues de la spécification HTML/CSS (figure 3).

couleurs_css4  mcolors.CSS4_COLORS
print(f"Nombre de couleurs CSS4  {len(couleurs_css4"
# graphique
gph = afficher_tableau_couleurs(
couleurs_css4,
titre="Couleurs CSS4 CSS4_COLORS  triees par teinte",
nombre_colonnes=4,
trier_par_teinte=True
)
[Link]("f12/couleurs_css4.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Nombre de couleurs CSS4 : 148


Visualiser les couleurs prédéfinies de Matplotlib 123
Version CSS4 triée par ordre alphabétique (figure 4).

gph = afficher_tableau_couleurs(
couleurs_css4,
titre="Couleurs CSS4 CSS4_COLORS  ordre alphabetique",
nombre_colonnes=4,
trier_par_teinte=False
)
[Link]("f12/couleurs_css4_trier.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Figure n°3
124 Visualiser les couleurs prédéfinies de Matplotlib

Figure n°4

Couleurs XKCD

Il y a 949 couleurs issues du grand sondage XKCD. Elles sont accessibles via le préfixe xkcd:
(ex: xkcd:sky blue). Comme elles sont nombreuses, on les a iche avec plus de colonnes. La
figure 5 en visualise une petite portion.

couleurs_xkcd = mcolors.XKCD_COLORS
print(f"Nombre de couleurs XKCD  {len(couleurs_xkcd)}")
# Pour la lisibilite, on enleve le prefixe ‘xkcd:’ dans l’affichage
couleurs_xkcd_propres = {
[Link]("xkcd:", ""): valeur
for nom, valeur in couleurs_xkcd.items() }
Visualiser les couleurs prédéfinies de Matplotlib 125

Figure n°5
126 Visualiser les couleurs prédéfinies de Matplotlib

# graphique
gph = afficher_tableau_couleurs(
couleurs_xkcd_propres,
titre="Couleurs XKCD XKCD_COLORS  triees par teinte",
nombre_colonnes=5,
trier_par_teinte=True
)
[Link]("f12/couleurs_xkcd.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Nombre de couleurs XKCD : 949

Fonction de recherche de couleur

Pour retrouver rapidement une couleur par nom, on ajoute la fonction rechercher_couleur().
Sur la figure 6, on recherche les couleurs qui contiennent le mot rose. Et sur les figures 7 et 8,
on recherche les couleurs qui contiennent le mot blue.

def rechercher_couleur(mot_cle, inclure_xkcd=True):


"""
Recherche les couleurs dont le nom contient le mot-cle.
Retourne un dictionnaire {nom: code_hex}.
"""
resultats = {}
sources = {
"BASE": mcolors.BASE_COLORS,
"TABLEAU": mcolors.TABLEAU_COLORS,
"CSS4": mcolors.CSS4_COLORS,
}
if inclure_xkcd:
sources["XKCD"] = mcolors.XKCD_COLORS
for nom_source, dictionnaire in [Link]():
for nom_couleur, valeur in [Link]():
if mot_cle.lower() in nom_couleur.lower():
cle_affichage = f"[{nom_source}] {nom_couleur}"
resultats[cle_affichage] = mcolors.to_hex(valeur)
return resultats
# Exemple : toutes les couleurs contenant ‘rose’
Visualiser les couleurs prédéfinies de Matplotlib 127
couleurs_rose = rechercher_couleur("rose")
print(f"Nombre de couleurs contenant ‘rose’ : {len(couleurs_rose)}")
# graphique
gph = afficher_tableau_couleurs(
couleurs_rose,
titre="Couleurs contenant ‘rose’",
nombre_colonnes=2,
trier_par_teinte=True
)
[Link]("f12/recherche_couleur_rose.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Nombre de couleurs contenant ‘rose’ : 11

Figure n°6

# Autre exemple : toutes les nuances de bleu


couleurs_bleu = rechercher_couleur("blue")
print(f"Nombre de couleurs contenant ‘blue’ : {len(couleurs_bleu)}")
# graphique
gph = afficher_tableau_couleurs(
couleurs_bleu,
titre="Couleurs contenant ‘blue’",
nombre_colonnes=3,
trier_par_teinte=True
)
[Link]("f12/recherche_couleur_bleu.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Nombre de couleurs contenant ‘blue’ : 157


128 Visualiser les couleurs prédéfinies de Matplotlib

Figure n°7
Visualiser les couleurs prédéfinies de Matplotlib 129
Figure n°8

Résumé

def afficher_resume_couleurs():
"""Affiche un resume du nombre de couleurs disponibles dans chaque famille."""
familles = {
"BASE_COLORS (couleurs de base)": mcolors.BASE_COLORS,
"TABLEAU_COLORS (palette par defaut)": mcolors.TABLEAU_COLORS,
"CSS4_COLORS (standard HTML/CSS": mcolors.CSS4_COLORS,
"XKCD_COLORS (sondage XKCD": mcolors.XKCD_COLORS
}
print("=" * 55
print("RESUME DES COULEURS PREDEFINIES DANS MATPLOTLIB")
print("=" * 55
total = 0
for nom_famille, dictionnaire in [Link]():
nombre = len(dictionnaire)
total += nombre
print(f" {nom_famille:42s} : {nombre:>5"
print("-" * 55
print(f" {‘TOTAL’42s} : {total:>5"
print("=" * 55
# test
afficher_resume_couleurs()
130 Visualiser les couleurs prédéfinies de Matplotlib

=======================================================
RESUME DES COULEURS PREDEFINIES DANS MATPLOTLIB
=======================================================
BASE_COLORS (couleurs de base) : 8
TABLEAU_COLORS (palette par defaut) : 10
CSS4_COLORS (standard HTML/CSS) : 148
XKCD_COLORS (sondage XKCD) : 949
-------------------------------------------------------
TOTAL : 1115
=======================================================
Visualiser les palettes de couleurs
prédéfinies de Matplotlib F13
Ce notebook a iche toutes les palettes de couleurs (colormaps) prédéfinies dans Matplotlib
sous forme de bandes dégradées avec leur nom. Matplotlib classe ses colormaps en plusieurs
catégories :
• Perceptuellement uniformes : viridis, plasma, inferno, magma, cividis.
• Séquentielles : dégradés simples (Blues, Greens, Reds, etc).
• Séquentielles (2) : autres dégradés (cool, hot, spring, etc).
• Divergentes : dégradés avec un point central (RdBu, coolwarm, etc).
• Cycliques : palettes qui bouclent (twilight, hsv).
• Qualitatives : couleurs discrètes (Set1, Pastel1, tab10, etc).
• Diverses : palettes mixtes (jet, rainbow, terrain, etc).
Tout le code source de programmation de cette fiche se trouve dans le fichier f13_matplotlib_
palettes_predefinies.ipynb placé dans le dossier NotebookJupyter de l’archive téléchargée.

Importation des bibliothèques


import numpy as np
import [Link] as plt
import matplotlib as mpl
132 Visualiser les palettes de couleurs prédéfinies de Matplotlib

Classification officielle des palettes

On reprend le classement o iciel de la documentation Matplotlib.

categories_palettes = {
"Perceptuellement uniformes": [
"viridis", "plasma", "inferno", "magma", "cividis"
],
"Sequentielles": [
"Greys", "Purples", "Blues", "Greens", "Oranges", "Reds",
"YlOrBr", "YlOrRd", "OrRd", "PuRd", "RdPu", "BuPu",
"GnBu", "PuBu", "YlGnBu", "PuBuGn", "BuGn", "YlGn"
],
"Sequentielles (2": [
"binary", "gist_yarg", "gist_gray", "gray", "bone", "pink",
"spring", "summer", "autumn", "winter", "cool", "Wistia",
"hot", "afmhot", "gist_heat", "copper"
],
"Divergentes": [
"PiYG", "PRGn", "BrBG", "PuOr", "RdGy", "RdBu", "RdYlBu",
"RdYlGn", "Spectral", "coolwarm", "bwr", "seismic"
],
"Cycliques": [
"twilight", "twilight_shifted", "hsv"
],
"Qualitatives": [
"Pastel1", "Pastel2", "Paired", "Accent", "Dark2", "Set1",
"Set2", "Set3", "tab10", "tab20", "tab20b", "tab20c"
],
"Diverses": [
"flag", "prism", "ocean", "gist_earth", "terrain", "gist_stern",
"gnuplot", "gnuplot2", "CMRmap", "cubehelix", "brg",
"gist_rainbow", "rainbow", "jet", "turbo", "nipy_spectral",
"gist_ncar"
]
}
Visualiser les palettes de couleurs prédéfinies de Matplotlib 133
# Affichage du nombre de palettes par categorie
total_palettes = 0
for nom_categorie, liste in categories_palettes.items():
print(f"{nom_categorie:35s} : {len(liste)} palettes")
total_palettes += len(liste)
print(f"{‘TOTAL’35s} : {total_palettes} palettes")

Perceptuellement uniformes : 5 palettes


Sequentielles : 18 palettes
Sequentielles (2) : 16 palettes
Divergentes : 12 palettes
Cycliques : 3 palettes
Qualitatives : 12 palettes
Diverses : 17 palettes
TOTAL : 83 palettes

Fonction principale de visualisation

On construit une fonction a icher_palettes() qui a iche une liste de palettes sous forme de
bandes dégradées.

def afficher_palettes(liste_palettes, titre, largeur=12, hauteur_par_palette=0.5,


ratio_colonnes=(1, 10
"""
Affiche une liste de palettes sous forme de table a 2 colonnes :
nom a gauche, bande de couleur a droite.
Parametres
----------
liste_palettes : list
Liste des noms de colormaps a afficher.
titre : str
Titre du tableau.
largeur : float
Largeur de la figure en pouces.
hauteur_par_palette : float
Hauteur de chaque ligne en pouces.
ratio_colonnes : tuple
Ratio de largeur (colonne_nom, colonne_palette).
134 Visualiser les palettes de couleurs prédéfinies de Matplotlib

"""
# Gradient horizontal de 0 a 1
gradient = [Link](0, 1, 256.reshape(1, 1
gradient = [Link]([gradient, gradient])
nombre_palettes = len(liste_palettes)
hauteur_totale = hauteur_par_palette * nombre_palettes + 1.0
# Grille : N lignes x 2 colonnes (nom | palette)
figure, axes = [Link](
nrows=nombre_palettes,
ncols=2,
figsize=(largeur, hauteur_totale),
facecolor=’whitesmoke’,
dpi=300,
gridspec_kw={‘width_ratios’: ratio_colonnes, ‘wspace’ 0.05, ‘hspace’ 0.3
)
[Link](titre, fontsize=14, fontweight="bold", y=1.0, family=’Roboto Condensed’)
# Si une seule palette, axes est 1D → on le passe en 2D
if nombre_palettes == 1
axes = [Link]([axes])
for ligne in range(nombre_palettes):
axe_nom = axes[ligne, 0
axe_palette = axes[ligne, 1
nom_palette = liste_palettes[ligne]
# Colonne de gauche : nom de la palette
axe_nom.text(
1.0, 0.5, nom_palette,
va="center", ha="right",
fontsize=12,
family="Roboto Condensed",
transform=axe_nom.transAxes
)
axe_nom.set_axis_off()
# Colonne de droite : bande de couleur
axe_palette.imshow(gradient, aspect="auto", cmap=plt.get_cmap(nom_palette))
axe_palette.set_axis_off()
[Link]()
return figure
Visualiser les palettes de couleurs prédéfinies de Matplotlib 135

Affichage par catégorie

Perceptuellement uniformes
Ces palettes sont recommandées pour la plupart des usages scientifiques car elles préservent
les di érences de valeurs de manière uniforme à l’œil (figure 1).

gph = afficher_palettes(
categories_palettes["Perceptuellement uniformes"],
titre="Palettes perceptuellement uniformes"
)
[Link]("f13/palette_uniforme.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Figure n°1

Séquentielles

Idéales pour représenter des données ordonnées qui vont du clair au foncé (figure 2).

# graphique
gph = afficher_palettes(
categories_palettes["Sequentielles"],
titre="Palettes sequentielles"
)
# sauvegarde
[Link]("f13/palette_sequentielle.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)
136 Visualiser les palettes de couleurs prédéfinies de Matplotlib

Figure n°2

Séquentielles (famille 2)

Idéales pour représenter des données ordonnées qui vont du clair au foncé (figure 3).

gph = afficher_palettes(
categories_palettes["Sequentielles (2",
titre="Palettes sequentielles (famille 2"
)
[Link]("f13/palette_sequentielle_famille_2.png",facecolor=’whitesmoke’,dpi=300,
bbox_inches=’tight’)
Visualiser les palettes de couleurs prédéfinies de Matplotlib 137

Figure n°3

Divergentes

Idéales pour représenter des données avec un point de référence central comme le zéro, la
moyenne, le seuil (figure 4).

# graphique
gph = afficher_palettes(
categories_palettes["Divergentes"],
titre="Palettes divergentes"
)
[Link]("f13/palette_divergente.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)
138 Visualiser les palettes de couleurs prédéfinies de Matplotlib

Figure n°4

Cycliques

Pour des données qui bouclent comme les angles, les heures, les phases (figure 5).

Figure n°5

gph = afficher_palettes(
categories_palettes["Cycliques"],
titre="Palettes cycliques"
Visualiser les palettes de couleurs prédéfinies de Matplotlib 139
)
[Link]("f13/palette_cyclique.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Qualitatives

Pour des catégories distinctes non ordonnées comme les classes, les groupes (figure 6).

gph = afficher_palettes(
categories_palettes["Qualitatives"],
titre="Palettes qualitatives"
)
[Link]("f13/palette_qualitative.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Figure n°6

Diverses

Pour des graphiques divers et variés (figure 7).


140 Visualiser les palettes de couleurs prédéfinies de Matplotlib

gph = afficher_palettes(
categories_palettes["Diverses"],
titre="Palettes diverses"
)
[Link]("f13/palette_diverses.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Figure n°7

Affichage d’une catégorie au choix

Fonction utilitaire a icher_categorie() pour a icher n’importe quelle catégorie.

def afficher_categorie(nom_categorie):
Visualiser les palettes de couleurs prédéfinies de Matplotlib 141
"""Affiche les palettes d’une categorie donnee."""
if nom_categorie not in categories_palettes:
print(f"Categorie inconnue. Disponibles : {list(categories_palettes.keys())}")
return
gph = afficher_palettes(
categories_palettes[nom_categorie],
titre=f"Palettes : {nom_categorie}"
)
return gph
# Exemple
gph = afficher_categorie("Qualitatives")

Versions inversées (avec _r)

Toutes les palettes peuvent être inversées en ajoutant le su ixe _r à leur nom (par exemple
avec viridis_r, Blues_r, RdBu_r). Sur la figure 8, on teste la fonction avec les palettes viridis et
viridis_r.

def comparer_palette_et_inverse(nom_palette):
"""Affiche une palette et sa version inversee cote a cote."""
gph = afficher_palettes(
[nom_palette, f"{nom_palette}_r"],
titre=f"Comparaison : {nom_palette} vs {nom_palette}_r"
)
return gph
# exemple
gph = comparer_palette_et_inverse("viridis")
[Link]("f13/palette_viridis_et_inverse.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Figure n°8
142 Visualiser les palettes de couleurs prédéfinies de Matplotlib

Recherche de palette par mot-clé

La fonction rechercher_palette() recherche les palettes qui contiennent le mot-clé passé en


paramètre. C’est ce que l’on fait sur la figure 9 en cherchant les palettes contenant le mot-clé
blue.

def rechercher_palette(mot_cle):
"""Recherche les palettes dont le nom contient le mot-cle."""
toutes_palettes = sorted([Link]())
# On exclut les versions inversees pour la lisibilite
palettes_filtrees = [
nom for nom in toutes_palettes
if mot_cle.lower() in [Link]() and not [Link]("_r")
]
if not palettes_filtrees:
print(f"Aucune palette trouvee pour ‘{mot_cle}’.")
return
print(f"Palettes trouvees pour ‘{mot_cle}’ : {len(palettes_filtrees)}")
gph = afficher_palettes(
palettes_filtrees,
titre=f"Palettes contenant ‘{mot_cle}’"
)
return gph
# Exemple
gph = rechercher_palette("blue")
[Link]("f13/palette_rechercher_blue.png",facecolor=’whitesmoke’,dpi=300,bbox_inches=’tight’)

Palettes trouvees pour ‘blue’ : 1

Figure n°9
Visualiser les palettes de couleurs prédéfinies de Matplotlib 143

Liste complète de toutes les palettes disponibles

Pour avoir la liste exhaustive (y compris les versions inversées).

def lister_toutes_palettes(inclure_inversees=False):
"""Retourne la liste complete des palettes disponibles."""
toutes = sorted([Link]())
if not inclure_inversees:
toutes = [nom for nom in toutes if not [Link]("_r")]
return toutes
# test
liste_sans_inversees = lister_toutes_palettes(inclure_inversees=False)
liste_avec_inversees = lister_toutes_palettes(inclure_inversees=True)
print(f"Nombre de palettes (sans inversees) : {len(liste_sans_inversees)}")
print(f"Nombre de palettes (avec inversees) : {len(liste_avec_inversees)}")
print("Extrait des 20 premieres :")
for nom in liste_sans_inversees[:20]:
print(f" - {nom}")

Nombre de palettes (sans inversees) : 90


Nombre de palettes (avec inversees) : 180
Extrait des 20 premieres :
- Accent
- Blues
- BrBG
- BuGn
- BuPu
- CMRmap
- Dark2
- GnBu
- Grays
- Greens
- Greys
- OrRd
- Oranges
- PRGn
- Paired
144 Visualiser les palettes de couleurs prédéfinies de Matplotlib

- Pastel1
- Pastel2
- PiYG
- PuBu
- PuBuGn

Résumé final

def afficher_resume_palettes():
"""Affiche un resume des palettes par categorie."""
print("=" * 60
print("RESUME DES PALETTES DE COULEURS MATPLOTLIB")
print("=" * 60
total = 0
for nom_categorie, liste in categories_palettes.items():
print(f" {nom_categorie:35s} : {len(liste):>3} palettes")
total += len(liste)
print("-" * 60
print(f" {‘TOTAL (categorisees)’35s} : {total:>3 palettes")
print(f" {‘TOTAL (disponibles sans _r)’35s} : {len(lister_toutes_palettes(False)):>3} palettes")
print(f" {‘TOTAL (avec versions inversees _r)’35s} : {len(lister_toutes_palettes(True)):>3 palettes")
print("=" * 60
# test
afficher_resume_palettes()

============================================================
RESUME DES PALETTES DE COULEURS MATPLOTLIB
============================================================
Perceptuellement uniformes : 5 palettes
Sequentielles : 18 palettes
Sequentielles (2) : 16 palettes
Divergentes : 12 palettes
Cycliques : 3 palettes
Qualitatives : 12 palettes
Diverses : 17 palettes
------------------------------------------------------------
TOTAL (categorisees) : 83 palettes
TOTAL (disponibles sans _r) : 90 palettes
Visualiser les palettes de couleurs prédéfinies de Matplotlib 145
TOTAL (avec versions inversees _r) : 180 palettes
============================================================
Exemples pratiques avec Matplotlib F14
Matplotlib o re de nombreuses façons de créer des visualisations statiques, animées et
interactives. C’est la bibliothèque de tracé la plus populaire pour Python. Elle fonctionne
facilement avec les tableaux NumPy et Pandas. Seaborn, quand à lui, étend encore plus les
fonctionnalités de Matplotlib. Vous pouvez l’installer avec la commande pip install matplotlib.
Le site web [Link] est une excellente page à consulter lorsque
vous cherchez des informations sur la création d’un type de graphique spécifique.
Tout le code source de programmation de cette fiche se trouve dans le fichier f14_matplotlib_
test_graphique.ipynb placé dans le dossier NotebookJupyter de l’archive téléchargée.

Importation des bibliothèques

import [Link] as plt


%matplotlib inline
import numpy as np
import pandas as pd
# Rechargement automatique du notebook lors des modifications
%reload_ext autoreload
%autoreload 2
148 Exemples pratiques avec Matplotlib

1 - Graphique fonctionnel

On commence par un graphique simple (figure 1) qui visualise une courbe rouge représentant
l’équation y = x² passant par les points (0,0), (1,1), (2,4), (3,9), (4,16) et (5,25), le tout sur un fond
beige clair avec une grille discrète.
Figure n°1

# Creer des tableaux NumPy x & y


# x contient les entiers de 0 à 5
# y contient les carrés y = x**2
abscisses = [Link](0, 5, 6, dtype=int)
print("abscisses =",abscisses)
ordonnees = abscisses ** 2
print("ordonnees =",ordonnees)
Exemples pratiques avec Matplotlib 149
# graphique
[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’16’
})
# Afficher le graphique avec x & y
fig, ax = [Link](1,1,figsize=(15,10,facecolor=’oldlace’,dpi=300
[Link](abscisses, ordonnees, color=’red’, lw=2.0, label=’équation y = x^2’)
# Ajouter un titre
[Link](‘Graphique des nombres entiers (0 à 5 élevé au carré’,fontsize=22,fontweight=’bold’)
# Ajouter un label X & Y
[Link](‘Nombre entier’)
[Link](‘Nombre entier au carré’)
[Link](loc=’upper left’,facecolor=’whitesmoke’,edgecolor=’black’,labelcolor=’blue’)
[Link](True,color=’gray’,alpha=0.3
[Link]("f14/graphique_01.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

abscisses = [0 1 2 3 4 5]
ordonnees = [ 0 1 4 9 16 25]

Ce code Python génère un graphique représentant les nombres entiers de 0 à 5 élevés au


carré. Voici ce qu’il fait, étape par étape.

Création des données

abscisses = [Link](0, 5, 6, dtype=int)


ordonnees = abscisses 2

La fonction [Link](0, 5, 6, dtype=int) génère 6 nombres entiers répartis uniformément


entre 0 et 5, soit [0, 1, 2, 3, 4, 5]. Ces valeurs sont stockées dans la variable abscisses (axe
horizontal). Ensuite, chaque valeur est élevée au carré avec abscisses ** 2, ce qui donne [0, 1,
4, 9, 16, 25], stocké dans ordonnees (axe vertical). Les deux print() a ichent simplement ces
valeurs dans la console pour vérification.

Configuration de l’apparence du texte

[Link]({
‘[Link]’:’Roboto Condensed’,
150 Exemples pratiques avec Matplotlib

‘[Link]’:’16’
})

Cette instruction définit les paramètres globaux du graphique : la police de caractères utilisée
sera Roboto Condensed et la taille par défaut du texte sera de 16 points.

Création de la figure

fig, ax = [Link](1,1,figsize=(15,10,facecolor=’oldlace’,dpi=300

On crée une figure contenant un seul graphique (1,1), de dimensions 15×10 pouces, avec
un fond couleur oldlace (blanc cassé) et une résolution de 300 points par pouce (qualité
impression).

Tracé de la courbe

[Link](abscisses, ordonnees, color=’red’, lw=2.0, label=’équation y = x^2’)

La méthode plot() trace la courbe en rouge, avec une épaisseur de trait de 2 pixels (lw =
linewidth). Le label sera a iché dans la légende.

Titre et étiquettes des axes

[Link](‘Graphique des nombres entiers (0 à 5 élevé au carré’, fontsize=22, fontweight=’bold’)


[Link](‘Nombre entier’)
[Link](‘Nombre entier au carré’)

On ajoute un titre en gras de 22 points au-dessus du graphique, ainsi que les étiquettes des
axes X et Y.

Légende et grille

# personnalisation
[Link](loc=’upper left’, facecolor=’whitesmoke’, edgecolor=’black’, labelcolor=’blue’)
[Link](True, color=’gray’, alpha=0.3

La légende est placée en haut à gauche, avec un fond whitesmoke, une bordure noire et
un texte en bleu. Une grille grise semi-transparente (alpha=0.3) est ajoutée pour faciliter la
lecture des valeurs.
Exemples pratiques avec Matplotlib 151

Sauvegarde et aƯichage

[Link]("f14/graphique_01.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300


[Link]()

Le graphique est enregistré au format PNG dans le dossier f14, avec un cadrage serré (bbox_
inches=’tight’) pour éviter les marges blanches inutiles. Enfin, [Link]() a iche le graphique
à l’écran.

Résultat attendu

Une courbe rouge représentant une partie de la parabole y = x² passant par les points (0,0),
(1,1), (2,4), (3,9), (4,16) et (5,25), le tout sur un fond beige clair avec une grille discrète.

2 - Afficher plusieurs graphiques

Ce code Python (figure 2) génère deux graphiques côte à côte : le premier représente les
nombres entiers de 0 à 5 élevés au carré, le second les mêmes nombres entiers élevés au
cube.
Figure n°2

# Creer des tableaux NumPy x & y


# x contient les entiers de 0 à 5
abscisses = [Link](0, 5, 6, dtype=int)
print("abscisses =",abscisses)
152 Exemples pratiques avec Matplotlib

# y contient les carrés y = x**2


ordonnees_eq1  abscisses ** 2
print("ordonnees_eq1 ",ordonnees_eq1
# y contient les carrés y = x**3
ordonnees_eq2  abscisses ** 3
print("ordonnees_eq2 ",ordonnees_eq2
# graphique
[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’14’
})
# Afficher le graphique avec x & y
fig, axes = [Link](1,2,figsize=(15,5,facecolor=’oldlace’,dpi=300
axes[0].plot(abscisses, ordonnees_eq1, color=’red’, lw=2.0, label=’équation y = x^2’)
axes[0].set_xlabel(‘Nombre entier’)
axes[0].set_ylabel(‘Nombre entier au carré’)
axes[0].legend(loc=’upper left’,facecolor=’whitesmoke’,edgecolor=’black’,labelcolor=’blue’)
axes[0].grid(True,color=’gray’,alpha=0.3
axes[0].set_title(‘Graphique des nombres entiers (0 à 5 élevé au carré’)
axes[1].plot(abscisses, ordonnees_eq2, color=’green’, lw=2.0, label=’équation y = x^3’)
axes[1].set_xlabel(‘Nombre entier’)
axes[1].set_ylabel(‘Nombre entier au cube’)
axes[1].legend(loc=’upper left’,facecolor=’whitesmoke’,edgecolor=’black’,labelcolor=’blue’)
axes[1].grid(True,color=’gray’,alpha=0.3
axes[1].set_title(‘Graphique des nombres entiers (0 à 5 élevé au cube’)
[Link]("Deux graphiques l’un à côté de l’autre",fontsize=22,fontweight=’bold’,y=1.01
[Link]("f14/graphique_02.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

abscisses = [0 1 2 3 4 5]
ordonnees_eq1 = [ 0 1 4 9 16 25]
ordonnees_eq2 = [ 0 1 8 27 64 125]

Avec ce code, on génère deux graphiques côte à côte : le premier graphique côté gauche
représente les nombres entiers de 0 à 5 élevés au carré, et le second graphique côté droit les
mêmes nombres entiers élevés au cube.
Exemples pratiques avec Matplotlib 153

Création des données

abscisses = [Link](0, 5, 6, dtype=int)


ordonnees_eq1  abscisses**2
ordonnees_eq2  abscisses**3

La fonction [Link](0, 5, 6, dtype=int) crée 6 nombres entiers répartis uniformément entre


0 et 5, soit [0, 1, 2, 3, 4, 5], stockés dans abscisses. On calcule ensuite deux séries de valeurs
verticales :
• ordonnees_eq1 contient les carrés [0, 1, 4, 9, 16, 25].
• ordonnees_eq2 contient les cubes [0, 1, 8, 27, 64, 125].
Les instructions print() a ichent ces valeurs dans la console pour vérification.

Configuration de l’apparence du texte

[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’14’
})

Cette instruction définit les paramètres globaux : la police Roboto Condensed et une taille de
texte par défaut de 14 points.

Création de la figure avec deux sous-graphiques

fig, axes = [Link](1,2,figsize=(15,5,facecolor=’oldlace’,dpi=300

Ici, on crée une figure divisée en 1 ligne et 2 colonnes par (1,2), ce qui produit deux zones
de tracé côte à côte. La variable axes est un tableau contenant les deux sous-graphiques :
axes[0] à gauche et axes[1] à droite. La figure mesure 15×5 pouces, avec un fond oldlace et
une résolution de 300 dpi.

Premier graphique (à gauche)

axes[0].plot(abscisses, ordonnees_eq1, color=’red’, lw=2.0, label=’équation y = x^2’)


axes[0].set_xlabel(‘Nombre entier’)
axes[0].set_ylabel(‘Nombre entier au carré’)
axes[0].legend(loc=’upper left’, facecolor=’whitesmoke’, edgecolor=’black’, labelcolor=’blue’)
axes[0].grid(True, color=’gray’, alpha=0.3
154 Exemples pratiques avec Matplotlib

axes[0].set_title(‘Graphique des nombres entiers (0 à 5 élevé au carré’)

On configure uniquement le premier sous-graphique en accédant à axes[0] :


• La courbe y = x2 est tracée en rouge avec une épaisseur de 2 pixels.
• Les axes X et Y sont étiquetés.
• La légende est placée en haut à gauche.
• Une grille grise semi-transparente est ajoutée.
• Un titre local est placé au-dessus de ce sous-graphique.

Second graphique (à droite)

axes[1].plot(abscisses, ordonnees_eq2, color=’green’, lw=2.0, label=’équation y = x^3’)


axes[1].set_xlabel(‘Nombre entier’)
axes[1].set_ylabel(‘Nombre entier au cube’)
axes[1].legend(loc=’upper left’, facecolor=’whitesmoke’, edgecolor=’black’, labelcolor=’blue’)
axes[1].grid(True, color=’gray’, alpha=0.3
axes[1].set_title(‘Graphique des nombres entiers (0 à 5 élevé au cube’)

On configure de la même manière axes[1], mais avec :


• Une courbe verte représentant y = x³.
• Des étiquettes adaptées (au cube).
• Un titre local approprié.

Titre global de la figure

[Link]("Deux graphiques l’un à côté de l’autre", fontsize=22, fontweight=’bold’, y=1.01

La méthode [Link]() ajoute un titre principal au-dessus des deux sous-graphiques. Le


paramètre y=1.01 le positionne légèrement au-dessus de la zone de tracé pour éviter qu’il ne
chevauche les titres individuels.
À noter qu’il y a une di érence importante entre set_title() (titre d’un sous-graphique, appelé
sur axes[0] ou axes[1]) et suptitle() (titre global de la figure entière, appelé sur fig).

Sauvegarde et aƯichage

[Link]("f14/graphique_02.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300


[Link]()

La figure complète (incluant les deux sous-graphiques) est enregistrée au format PNG dans le
dossier f14, avec un cadrage serré. Enfin, [Link]() a iche le résultat à l’écran.
Exemples pratiques avec Matplotlib 155

Résultat attendu

Une figure composée de deux graphiques alignés horizontalement :


• À gauche, une parabole rouge (y = x²) passant par (5, 25).
• À droite, une courbe cubique verte (y = x³) passant par (5, 125).
Le tout surmonté d’un titre global en gras, avec un fond beige clair uniforme.

3 - Afficher plusieurs courbes sur un même graphique

Ce code Python trace deux courbes superposées sur un même graphique (figure 3) : les
nombres entiers de 0 à 5 élevés au carré (en rouge) et au cube (en vert).
Figure n°3

# Creer des tableaux NumPy x & y


# x contient les entiers de 0 à 5
abscisses = [Link](0, 5, 6, dtype=int)
print("abscisses =",abscisses)
# y contient les carrés y = x**2
ordonnees_eq1  abscisses ** 2
156 Exemples pratiques avec Matplotlib

print("ordonnees_eq1 ",ordonnees_eq1
# y contient les carrés y = x**3
ordonnees_eq2  abscisses ** 3
print("ordonnees_eq2 ",ordonnees_eq2
# graphique
[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’14’
})
# Afficher le graphique avec x & y
fig, ax = [Link](1,1,figsize=(15,8,facecolor=’oldlace’,dpi=300
[Link](abscisses, ordonnees_eq1, color=’red’, lw=2.0, label=’équation y = x^2’)
[Link](abscisses, ordonnees_eq2, color=’green’, lw=2.0, label=’équation y = x^3’)
ax.set_xlabel(‘Nombre entier’)
ax.set_ylabel(‘Nombre entier élevé au carré et au cube’)
ax.set_yticks(range(0, 151, 10
[Link](loc=’upper left’,facecolor=’whitesmoke’,edgecolor=’black’,labelcolor=’blue’)
[Link](True,color=’gray’,alpha=0.3
ax.set_title(‘Graphique des nombres entiers (0 à 5 élevé au carré et au cube’,fontsize=22,
fontweight=’bold’,y=1.02
[Link]("f14/graphique_03.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

abscisses = [0 1 2 3 4 5]
ordonnees_eq1 = [ 0 1 4 9 16 25]
ordonnees_eq2 = [ 0 1 8 27 64 125]

Ce code Python trace deux courbes superposées sur un même graphique : les nombres
entiers de 0 à 5 élevés au carré (en rouge) et au cube (en vert).

Création des données

abscisses = [Link](0, 5, 6, dtype=int)


ordonnees_eq1  abscisses**2
ordonnees_eq2  abscisses**3

La fonction [Link](0, 5, 6, dtype=int) crée 6 nombres entiers répartis uniformément entre


0 et 5, soit [0, 1, 2, 3, 4, 5], stockés dans abscisses. On calcule ensuite deux séries de valeurs
Exemples pratiques avec Matplotlib 157
verticales :
• ordonnees_eq1 contient les carrés [0, 1, 4, 9, 16, 25].
• ordonnees_eq2 contient les cubes [0, 1, 8, 27, 64, 125].
Les instructions print() a ichent ces valeurs dans la console pour vérification.

Configuration de l’apparence du texte

[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’14’
})

Cette instruction définit les paramètres globaux : la police Roboto Condensed et une taille de
texte par défaut de 14 points.

Création de la figure

fig, ax = [Link](1,1,figsize=(15,8,facecolor=’oldlace’,dpi=300

On crée une figure contenant un seul graphique par (1,1), de dimensions 15×8 pouces, avec
un fond oldlace et une résolution de 300 dpi.
Point important - Contrairement à l’exemple précédent avec deux sous-graphiques, ici ax est
une seule zone de tracé unique (et non un tableau). On y ajoutera les deux courbes l’une par-
dessus l’autre.

Tracé des deux courbes sur le même axe

[Link](abscisses, ordonnees_eq1, color=’red’, lw=2.0, label=’équation y = x^2’)


[Link](abscisses, ordonnees_eq2, color=’green’, lw=2.0, label=’équation y = x^3’)

La méthode plot() est appelée deux fois sur le même axe ax. C’est le principe de la superposition
dans laquelle chaque appel ajoute une nouvelle courbe sans e acer la précédente :
• La première courbe est rouge pour y = x² .
• La seconde courbe est verte pour y = x³ .
Les deux label alimenteront automatiquement la légende.

Étiquettes des axes

ax.set_xlabel(‘Nombre entier’)
158 Exemples pratiques avec Matplotlib

ax.set_ylabel(‘Nombre entier élevé au carré et au cube’)

L’axe horizontal est étiqueté Nombre entier et l’axe vertical reçoit une étiquette combinée,
puisqu’il représente à la fois les carrés et les cubes.

Personnalisation des graduations verticales

ax.set_yticks(range(0, 151, 10

Cette ligne est nouvelle par rapport aux exemples précédents. La méthode set_yticks() impose
les graduations de l’axe Y : range(0, 151, 10) génère les valeurs [0, 10, 20, 30, ..., 150], soit une
graduation tous les 10 unités, de 0 à 150. Cela permet une lecture plus précise, d’autant plus
utile que les cubes montent jusqu’à 125.

Légende et grille

[Link](loc=’upper left’, facecolor=’whitesmoke’, edgecolor=’black’, labelcolor=’blue’)


[Link](True, color=’gray’, alpha=0.3

La légende est placée en haut à gauche. Elle a ichera automatiquement les deux équations
avec leurs couleurs respectives, ce qui permet de distinguer visuellement les deux courbes.
Une grille grise semi-transparente facilite la lecture des valeurs.

Titre du graphique

ax.set_title(‘Graphique des nombres entiers (0 à 5 élevé au carré et au cube’,


fontsize=22, fontweight=’bold’, y=1.02

Le titre, en gras et de taille 22, est placé au-dessus du graphique. Le paramètre y=1.02 le
décale légèrement vers le haut pour laisser un peu d’espace respirable entre le titre et la zone
de tracé.

Sauvegarde et aƯichage

# affichage
[Link]("f14/graphique_03.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300
[Link]()

Le graphique est enregistré au format PNG dans le dossier f14 avec un cadrage serré, puis
a iché à l’écran via [Link]().
Exemples pratiques avec Matplotlib 159

Résultat attendu

Un unique graphique contenant :


• Une courbe rouge (y = x²) relativement plate, montant jusqu’à 25.
• Une courbe verte (y = x³) qui démarre au même point (0,0) mais qui grimpe beaucoup plus
rapidement jusqu’à 125.
La superposition permet de comparer visuellement la croissance des deux fonctions. Elles
sont quasi confondues près de l’origine, puis la courbe cubique s’envole nettement au-dessus
de la parabole à partir de x = 2.

4 - Options d’apparence

Dans ce paragraphe, on trace deux courbes stylisées sur un même graphique (figure 4), avec
des marqueurs personnalisés, un style de trait di érent pour chaque équation, et une grille
avec un motif de tirets particulier.
Figure n°4

# Creer des tableaux NumPy x & y


# x contient les entiers de 0 à 5
abscisses = [Link](0, 5, 6, dtype=int)
160 Exemples pratiques avec Matplotlib

print("abscisses =",abscisses)
# y contient les carrés y = x**2
ordonnees_eq1  abscisses ** 2
print("y = x**2  ordonnees_eq1 ",ordonnees_eq1
# y contient les carrés y = x**3  10
ordonnees_eq2  abscisses ** 3  10
print("y = x**3 10  ordonnees_eq2 ",ordonnees_eq2
# graphique
[Link]({
‘[Link]’:’Roboto Condensed’, ‘[Link]’:’14’
})
# Afficher le graphique avec x & y
fig, ax = [Link](1,1,figsize=(15,8,facecolor=’oldlace’,dpi=300
[Link](abscisses, ordonnees_eq1, color=’red’, lw=2.0, label=’équation y = x^2’,
marker=’o’, markersize=12, markerfacecolor=’red’,
markeredgecolor=’black’, markeredgewidth=1.0
[Link](abscisses, ordonnees_eq2, color=’green’, lw=3.0, ls=’--’, label=’équation y = x^3  10’,
marker=’^’, markersize=12, markerfacecolor=’lime’,
markeredgecolor=’purple’, markeredgewidth=1.0
ax.set_xlabel(‘Nombre entier’)
ax.set_ylabel(‘Résultat de l\’équation’)
ax.set_yticks(range(0, 151, 10
[Link](loc=’upper left’,facecolor=’white’,edgecolor=’black’,labelcolor=’blue’)
[Link](True,color=’black’,alpha=0.3, dashes=(5, 2, 1, 2
ax.set_facecolor(‘whitesmoke’)
ax.set_title(‘Graphique des nombres entiers (0 à 5 selon deux équations spécifiques’,fontsize=22,
fontweight=’bold’,y=1.02
[Link]("f14/graphique_04.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

abscisses = [0 1 2 3 4 5]
y = x**2 : ordonnees_eq1 = [ 0 1 4 9 16 25]
y = x**3 +10 : ordonnees_eq2 = [ 10 11 18 37 74 135]

Ce code Python trace deux courbes stylisées sur un même graphique, avec des marqueurs
personnalisés, un style de trait di érent pour chaque équation, et une grille avec un motif de
tirets particulier.
Exemples pratiques avec Matplotlib 161

Création des données

abscisses = [Link](0, 5, 6, dtype=int)


ordonnees_eq1  abscisses** 2
ordonnees_eq2  abscisses**3  10

La fonction [Link](0, 5, 6, dtype=int) crée 6 nombres entiers répartis uniformément entre


0 et 5, soit [0, 1, 2, 3, 4, 5], stockés dans abscisses. On calcule ensuite deux séries de valeurs
verticales :
• ordonnees_eq1 contient les carrés par [0, 1, 4, 9, 16, 25].
• ordonnees_eq2 contient les cubes décalés de +10 par [10, 11, 18, 37, 74, 135].
Nouveauté - L’ajout de + 10 à la seconde équation décale toute la courbe vers le haut de 10
unités, évitant ainsi qu’elle ne démarre au même point que la première.
Les instructions print() a ichent ces valeurs dans la console pour vérification.

Configuration de l’apparence du texte

[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’14’
})

Cette instruction définit les paramètres globaux : la police Roboto Condensed et une taille de
texte par défaut de 14 points.

Création de la figure

fig, ax = [Link](1,1,figsize=(15,8,facecolor=’oldlace’,dpi=300

On crée une figure contenant un seul graphique par (1,1), de dimensions 15×8 pouces, avec
un fond oldlace et une résolution de 300 dpi.

Tracé de la première courbe avec marqueurs

[Link](abscisses, ordonnees_eq1, color=’red’, lw=2.0, label=’équation y = x^2’,


marker=’o’, markersize=12, markerfacecolor=’red’,
markeredgecolor=’black’, markeredgewidth=1.0

Cette ligne trace la parabole rouge, mais avec plusieurs nouveautés visuelles :
162 Exemples pratiques avec Matplotlib

• marker=’o’ : un marqueur circulaire est placé à chaque point de données.


• markersize=12 : les marqueurs ont un diamètre de 12 points.
• markerfacecolor=’red’ : l’intérieur du marqueur est rouge.
• markeredgecolor=’black’ : le contour du marqueur est noir.
• markeredgewidth=1.0 : l’épaisseur du contour est de 1 pixel.
Le résultat : une courbe rouge continue avec 6 pastilles rouges cerclées de noir à chaque
valeur entière.

Tracé de la seconde courbe avec style personnalisé

[Link](abscisses, ordonnees_eq2, color=’green’, lw=3.0, ls=’--’, label=’équation y = x^3  10’,


marker=’^’, markersize=12, markerfacecolor=’lime’,
markeredgecolor=’purple’, markeredgewidth=1.0

Cette seconde courbe introduit encore plus de personnalisation :


• lw=3.0 : trait plus épais que la première courbe (3 pixels au lieu de 2).
• ls=’--’ : style de ligne en tirets (dashed) au lieu d’une ligne continue.
• marker=’^’ : marqueurs en forme de triangle pointant vers le haut.
• markerfacecolor=’lime’ : triangles remplis en vert clair (lime).
• markeredgecolor=’purple’ : contour des triangles en violet.
Cette combinaison permet de di érencier visuellement et instantanément les deux courbes,
même en impression noir et blanc.

Étiquettes et graduations

ax.set_xlabel(‘Nombre entier’)
ax.set_ylabel(‘Résultat de l\’équation’)
ax.set_yticks(range(0, 151, 10

L’axe X est étiqueté Nombre entier et l’axe Y reçoit une étiquette générique (Résultat de
l’équation) adaptée au fait que deux équations di érentes sont tracées. Notez l’utilisation de \’
pour échapper l’apostrophe à l’intérieur de la chaîne délimitée par des apostrophes simples.
La méthode set_yticks() impose des graduations tous les 10 unités, de 0 à 150.

Légende et grille personnalisée

[Link](loc=’upper left’, facecolor=’white’, edgecolor=’black’, labelcolor=’blue’)


[Link](True, color=’black’, alpha=0.3, dashes=(5, 2, 1, 2

La légende est placée en haut à gauche, avec un fond blanc pur cette fois (au lieu de
Exemples pratiques avec Matplotlib 163
whitesmoke). La nouveauté principale concerne la grille avec le paramètre dashes=(5, 2, 1, 2)
qui définit un motif de tirets complexe, à lire par paires (trait, espace) :
• 5 pixels de trait, puis 2 pixels d’espace.
• 1 pixel de trait, puis 2 pixels d’espace.
• … et le motif se répète.
Cela produit une grille avec un motif alternant trait long / trait court (type tiret-point), plus
ra iné qu’une grille classique en pointillés.

Couleur de fond de la zone de tracé

ax.set_facecolor(‘whitesmoke’)

Cette ligne est nouvelle car elle définit la couleur de fond à l’intérieur de la zone de tracé en
whitesmoke (gris très clair). Il faut bien distinguer deux fonds di érents :
• fig avec facecolor=’oldlace’ : le fond autour du graphique (beige clair).
• ax.set_facecolor(‘whitesmoke’) : le fond du rectangle de tracé lui-même (gris très clair).
Ce contraste subtil met en valeur la zone où se trouvent les courbes.

Titre, sauvegarde et aƯichage

ax.set_title(‘Graphique des nombres entiers (0 à 5 selon deux équations spécifiques’,


fontsize=22, fontweight=’bold’, y=1.02
[Link]("f14/graphique_04.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300
[Link]()

Le titre en gras est décalé légèrement vers le haut (y=1.02). Le graphique est enregistré en PNG
dans le dossier f14, puis a iché.

Résultat attendu

Un graphique soigné présentant :


• Une courbe rouge continue (y = x²) avec des pastilles rouges cerclées de noir à chaque
point entier.
• Une courbe verte en tirets épais (y = x³ + 10) avec des triangles verts clairs cerclés de
violet.
• Un fond intérieur gris clair (whitesmoke) contrastant avec le fond extérieur beige (oldlace).
• Une grille noire discrète avec un motif de tirets alternés (long-court).
Les deux courbes sont maintenant nettement distinguables grâce aux di érences de couleur,
de style de trait et de forme de marqueurs, ce qui rend le graphique très lisible même en cas
d’impression ou pour des daltoniens.
164 Exemples pratiques avec Matplotlib

5 - DataFrame des ventes de glaces avec Faker

On génère un DataFrame Pandas df_ventes_glace contenant :


• La colonne temperature avec des valeurs entières entre 25 et 45 °C.
• La colonne nombre_glace avec des valeurs entières entre 122 et 433.
• Les données sont générées avec Faker en français avec la locale fr_FR.
La relation est croissante : plus la température est élevée, plus le nombre de glaces vendues
augmente (avec un peu de bruit aléatoire pour rester réaliste).
On instancie Faker avec la locale fr_FR et on fixe une graine (seed) pour que les résultats soient
reproductibles.

import pandas as pd
import numpy as np
from faker import Faker
import [Link] as plt
generateur_faker = Faker("fr_FR")
[Link](42)
[Link](42)
print(f"Locale de Faker : {generateur_faker.locales}")

Locale de Faker : [‘fr_FR’]

Stratégie pour garantir la corrélation croissante :


• On génère d’abord les températures (25 à 45) avec Faker par la fonction pyint().
• Pour chaque température, on calcule un nombre de glaces proportionnel sur l’intervalle
[122, 433].
• On ajoute un bruit aléatoire pour que les points ne soient pas parfaitement alignés.
• On borne ensuite les valeurs dans [122, 433] pour respecter la contrainte.

def generer_ventes_glace(nombre_lignes=100, temperature_min=25, temperature_max=45,


glace_min=122, glace_max=433, intensite_bruit=25
"""
Genere un DataFrame de ventes de glaces avec Faker (fr_FR.
La relation entre temperature et nombre_glace est croissante :
plus il fait chaud, plus il y a de ventes de glaces.
Parametres
----------
Exemples pratiques avec Matplotlib 165
nombre_lignes : int
Nombre de lignes a generer.
temperature_min, temperature_max : int
Plage de temperatures en degres.
glace_min, glace_max : int
Plage du nombre de glaces.
intensite_bruit : int
Ecart-type du bruit aleatoire ajoute.
Retourne
--------
[Link] avec les colonnes ‘temperature’ et ‘nombre_glace’.
"""
# Etape 1  generation des temperatures avec Faker
liste_temperatures = [
generateur_faker.pyint(min_value=temperature_min, max_value=temperature_max)
for _ in range(nombre_lignes)
]
# Etape 2  calcul de la proportion sur l’intervalle [0, 1
etendue_temperature = temperature_max - temperature_min
etendue_glace = glace_max - glace_min
liste_nombres_glaces = []
for temperature in liste_temperatures:
# Proportion lineaire entre 0 (temp_min) et 1 (temp_max)
proportion = (temperature - temperature_min) / etendue_temperature
# Valeur de base proportionnelle
valeur_base = glace_min + proportion * etendue_glace
# Ajout d’un bruit gaussien pour un rendu realiste
bruit = [Link](0, intensite_bruit)
valeur_avec_bruit = valeur_base + bruit
# Bornage dans l’intervalle [glace_min, glace_max] et conversion en entier
valeur_finale = int([Link](valeur_avec_bruit, glace_min, glace_max))
liste_nombres_glaces.append(valeur_finale)
# Etape 3  construction du DataFrame
dataframe_resultat = [Link]({
"temperature": liste_temperatures,
"nombre_glace": liste_nombres_glaces
})
166 Exemples pratiques avec Matplotlib

return dataframe_resultat
# test
df_ventes_glace = generer_ventes_glace(nombre_lignes=100
print(df_ventes_glace)

temperature nombre_glace
0 45 433
1 28 165
2 25 138
3 33 284
4 32 224
.. ... ...
95 33 209
96 27 160
97 31 221
98 43 402
99 35 271

[100 rows x 2 columns]

On e ectue un tri par ordre croissant des valeurs contenues dans la colonne temperature.

# Lire les donnees de ventes de glaces


df_trier_temperature = df_ventes_glace.sort_values(by=’temperature’)
print(df_trier_temperature)

temperature nombre_glace
2 25 138
29 25 122
19 25 122
13 25 122
45 26 122
.. ... ...
78 45 433
75 45 433
53 45 433
22 45 433
0 45 433

[100 rows x 2 columns]


Exemples pratiques avec Matplotlib 167

# Convertir de Pandas vers un tableau NumPy


tab_trier_temperature = df_trier_temperature.values
print(tab_trier_temperature)

[[ 25 138]
[ 25 122]
[ 25 122]
[ 25 122]
[ 26 122]
[ 26 161]
[ 26 139]
[ 26 122]
[ 26 143]
[ 27 161]
...
[ 44 409]
[ 44 433]
[ 44 394]
[ 45 433]
[ 45 433]
[ 45 433]
[ 45 433]
[ 45 433]
[ 45 433]
[ 45 433]]

Ce petit bout de code e ectue une conversion de structure de données. Il transforme un


DataFrame Pandas en un tableau NumPy classique.

La conversion

tab_trier_temperature = df_trier_temperature.values

L’attribut values appliqué à un DataFrame Pandas renvoie les données brutes sous forme de
tableau NumPy à deux dimensions (ndarray). Autrement dit, on extrait le contenu chi ré du
tableau Pandas sans conserver :
• Les noms de colonnes (l’en-tête).
• L’index (la première colonne de numérotation des lignes).
Seules les valeurs sont conservées, organisées en lignes et colonnes.
168 Exemples pratiques avec Matplotlib

L’aƯichage

print(tab_trier_temperature)

Cette instruction a iche le tableau NumPy dans la console. La présentation est plus sobre
que celle d’un DataFrame Pandas : pas de mise en forme tabulaire avec en-têtes, juste les
valeurs entre crochets.

Pourquoi faire cette conversion ?

Passer de Pandas à NumPy est utile dans plusieurs situations :


• Performance : les calculs numériques sont généralement plus rapides sur un ndarray
NumPy que sur un DataFrame.
• Compatibilité : certaines bibliothèques (Matplotlib, Scikit-learn, etc) acceptent ou
préfèrent les tableaux NumPy en entrée.
• Simplicité : lorsqu’on n’a plus besoin des étiquettes de colonnes ni de l’index, un tableau
NumPy su it.

À noter

L’attribut values est la méthode historique, mais Pandas recommande désormais d’utiliser
to_numpy() qui fait exactement la même chose de manière plus explicite.

tab_trier_temperature = df_trier_temperature.to_numpy()

Les deux écritures produisent un résultat identique dans la grande majorité des cas.

On poursuit avec ce code qui extrait deux colonnes distinctes d’un tableau NumPy à deux
dimensions pour les séparer en deux variables : l’une pour l’axe horizontal, l’autre pour l’axe
vertical d’un futur graphique.

# Recuperer les valeurs x & y et les mettre dans un tableau


abscisses = tab_trier_temperature[:, 0]
print("abscisses =\n",abscisses)
ordonnees = tab_trier_temperature[:, 1]
print("ordonnees =\n",ordonnees)

abscisses =
[25 25 25 25 26 26 26 26 26 27 27 27 27 27 27 27 27 28 28 28 28 28 28 29
29 30 30 30 30 31 31 31 31 31 31 32 32 32 32 32 32 32 32 32 33 33 33 33
Exemples pratiques avec Matplotlib 169
33 33 33 33 34 34 35 35 35 35 35 36 36 36 36 36 36 37 37 37 37 37 38 38
38 39 39 39 39 41 42 42 42 42 42 42 42 43 43 43 43 44 44 44 44 45 45 45
45 45 45 45]
ordonnees =
[138 122 122 122 122 161 139 122 143 161 161 122 122 125 160 166 155 165
187 188 122 177 187 223 204 236 184 208 150 209 221 207 254 201 184 239
255 217 233 218 205 200 224 224 180 219 244 284 209 209 231 233 245 257
271 282 277 269 290 290 331 292 276 297 316 298 288 264 342 313 310 370
312 326 310 364 328 378 350 394 380 412 376 374 422 390 411 402 380 409
409 433 394 433 433 433 433 433 433 433]

Extraction de la première colonne

abscisses = tab_trier_temperature[:, 0]

Cette ligne utilise le slicing NumPy (découpage) avec une syntaxe particulière à deux
dimensions. Décomposons [:, 0] :
• Le caractère ":" avant la virgule signifie toutes les lignes.
• Le 0 après la virgule signifie uniquement la colonne d’indice 0 (la première colonne,
puisque NumPy commence à compter à partir de 0).
Résultat : abscisses reçoit l’intégralité de la première colonne du tableau, sous forme d’un
tableau NumPy à une seule dimension (un vecteur).

Extraction de la seconde colonne

ordonnees = tab_trier_temperature[:, 1]

Sur le même principe, [:, 1] signifie toutes les lignes, colonne d’indice 1 (la deuxième colonne).
La variable ordonnees reçoit donc l’intégralité de cette seconde colonne.

Comprendre la syntaxe [lignes, colonnes]

Dans un tableau NumPy 2D, l’indexation suit toujours le schéma [lignes, colonnes]. Voici
quelques exemples dans le tableau ci-dessous pour bien en saisir le sens.

Syntaxe Signification

tab[0, 0] la valeur située ligne 0, colonne 0 (un seul nombre)

tab[:, 0] toutes les lignes de la colonne 0 (un vecteur colonne)


170 Exemples pratiques avec Matplotlib

tab[0, :] toutes les colonnes de la ligne 0 (un vecteur ligne)

tab[:, 1] toutes les lignes de la colonne 1

tab[0:3, 1] les lignes 0 à 2 de la colonne 1

À quoi ça sert ?

Vu le nom du tableau (tab_trier_temperature), on devine la structure suivante :


• La colonne 0 contient probablement des dates ou des identifiants (ce qui deviendra l’axe
X).
• La colonne 1 contient les valeurs de température (ce qui deviendra l’axe Y).
En séparant les deux colonnes dans des variables nommées abscisses et ordonnees, on
prépare le terrain pour un appel du type [Link](abscisses, ordonnees, ...) qui tracera la courbe
des températures au fil du temps ou des enregistrements.
On passe à la composition graphique pour obtenir le graphique de la figure 5. Ce code produit
un graphique combiné à double axe Y :
• Des barres bleues (ventes par tranche de température) superposées à une courbe rouge
(cumul des ventes).
• Les deux partageant le même axe X mais ayant leur propre échelle verticale.

Figure n°5
Exemples pratiques avec Matplotlib 171
# graphique
[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’14’
})
# Afficher le graphique avec x & y
fig, ax = [Link](1,1,figsize=(15,8,facecolor=’oldlace’,dpi=300
# graphique principal
[Link](abscisses,ordonnees,zorder=4,color=’blue’,label="ventes de glaces")
ax.set_xlabel(‘Températures’, color=’black’)
ax.set_ylabel(‘Ventes de glaces’, color=’blue’)
ax.tick_params(axis=’y’,labelcolor=’blue’)
# graphique secondaire partageant le meme X
ord_cum = [Link](ordonnees)
print("ord_cum =\n",ord_cum)
axe_secondaire = [Link]()
axe_secondaire.plot(abscisses, ord_cum, color=’red’, linewidth=3.0,
label=’Cumul des ventes de glaces’,zorder=5
axe_secondaire.set_ylabel(‘Ventes cumulées’, color=’red’)
axe_secondaire.tick_params(axis=’y’,labelcolor=’red’)
# personnalisation
[Link]("Deux graphiques partageant le même axe X",fontsize=22,fontweight=’bold’,y=0.95
[Link](True,color=’black’,alpha=0.3,zorder=0
# Afficher une legende unique sur l’un des deux axes (peu importe lequel)
# Recuperer les handles et labels de chaque axe
handles_1, labels_1  ax.get_legend_handles_labels()
handles_2, labels_2  axe_secondaire.get_legend_handles_labels()
[Link](handles_1  handles_2, labels_1  labels_2, loc=’upper left’,
facecolor=’whitesmoke’,edgecolor=’black’)
[Link]("f14/graphique_05.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

ord_cum =
[ 138 260 382 504 626 787 926 1048 1191 1352 1513 1635
1757 1882 2042 2208 2363 2528 2715 2903 3025 3202 3389 3612
3816 4052 4236 4444 4594 4803 5024 5231 5485 5686 5870 6109
6364 6581 6814 7032 7237 7437 7661 7885 8065 8284 8528 8812
9021 9230 9461 9694 9939 10196 10467 10749 11026 11295 11585 11875
172 Exemples pratiques avec Matplotlib

12206 12498 12774 13071 13387 13685 13973 14237 14579 14892 15202 15572
15884 16210 16520 16884 17212 17590 17940 18334 18714 19126 19502 19876
20298 20688 21099 21501 21881 22290 22699 23132 23526 23959 24392 24825
25258 25691 26124 26557]

Particularité : le graphique à double axe Y (twinx)

C’est la grande nouveauté de ce code. Lorsqu’on veut a icher sur un même graphique deux
séries de données dont les ordres de grandeur sont très di érents, un axe Y unique devient
problématique : si les ventes individuelles valent entre 10 et 200 unités alors que le cumul
monte jusqu’à 1500 unités, alors les barres paraîtraient écrasées en bas du graphique, car
l’échelle serait dominée par les grandes valeurs du cumul.
La solution est de créer un second axe Y indépendant, à droite du graphique, avec sa propre
échelle. Les deux axes partagent uniquement l’axe X. C’est ce qu’on appelle un graphique à
axe Y jumelé (twin axis).

Création de la figure et du graphique principal

fig, ax = [Link](1,1,figsize=(15,8,facecolor=’oldlace’,dpi=300
[Link](abscisses, ordonnees, zorder=4, color=’blue’, label="ventes de glaces")

On crée une figure unique, puis on trace un diagramme en barres avec [Link]() (et non [Link]()
comme dans les exemples précédents). Les barres sont bleues. Le paramètre zorder=4
contrôle l’ordre d’empilement (profondeur visuelle) : plus la valeur est élevée, plus l’élément
apparaît au premier plan. Les éléments avec un zorder plus faible sont dessinés en-dessous.

Personnalisation de l’axe Y principal

ax.set_xlabel(‘Températures’, color=’black’)
ax.set_ylabel(‘Ventes de glaces’, color=’blue’)
ax.tick_params(axis=’y’, labelcolor=’blue’)

L’étiquette Y et les graduations (ticks) de l’axe Y principal sont colorées en bleu, pour établir un
lien visuel immédiat avec les barres bleues. La méthode tick_params() permet de styliser les
graduations : ici, seules les graduations de l’axe Y (axis=’y’) reçoivent la couleur bleue.

Calcul du cumul des ventes

ord_cum = [Link](ordonnees)

La fonction [Link]() (cumulative sum) calcule la somme cumulée des valeurs. Si


Exemples pratiques avec Matplotlib 173
ordonnees = [10, 20, 30, 40], alors ord_cum = [10, 30, 60, 100]. Chaque valeur représente le
total accumulé depuis le début.

Création de l’axe secondaire

axe_secondaire = [Link]()

C’est l’instruction clé de ce graphique. La méthode twinx() crée un nouvel axe qui partage l’axe
X avec ax, mais dispose de son propre axe Y (placé à droite du graphique par défaut).
À noter qu’il existe aussi twiny() qui fait l’inverse (même axe Y, deux axes X), utilisé plus
rarement.

Tracé de la courbe cumulative sur l’axe secondaire

axe_secondaire.plot(abscisses, ord_cum, color=’red’, linewidth=3.0,


label=’Cumul des ventes de glaces’, zorder=5
axe_secondaire.set_ylabel(‘Ventes cumulées’, color=’red’)
axe_secondaire.tick_params(axis=’y’, labelcolor=’red’)

La courbe rouge épaisse est tracée sur l’axe secondaire, avec zorder=5 pour qu’elle passe
devant les barres bleues (zorder=4). L’étiquette et les graduations de droite sont également en
rouge, cohérent avec la couleur de la courbe.

Titre et grille

[Link]("Deux graphiques partageant le même axe X", fontsize=22, fontweight=’bold’, y=0.95


[Link](True, color=’black’, alpha=0.3, zorder=0

Le titre global est placé via [Link](). La grille reçoit zorder=0 pour apparaître tout en arrière-
plan, sous les barres et la courbe.

Fusion des deux légendes en une seule

C’est le second point technique important de ce code. Par défaut, chaque axe gère sa propre
légende. Si on appelait simplement [Link]() et axe_secondaire.legend(), on obtiendrait
deux légendes séparées, visuellement encombrantes.

handles_1, labels_1  ax.get_legend_handles_labels()


handles_2, labels_2  axe_secondaire.get_legend_handles_labels()
[Link](handles_1  handles_2, labels_1  labels_2, loc=’upper left’,
174 Exemples pratiques avec Matplotlib

facecolor=’whitesmoke’, edgecolor=’black’)

Décomposons ce mécanisme :
• get_legend_handles_labels() renvoie deux listes : les handles (les objets graphiques, ici la
barre bleue et la ligne rouge) et les labels (les textes associés).
• On récupère ces listes pour chacun des deux axes.
• On les concatène avec l’opérateur +.
• On passe les listes fusionnées à [Link]() pour créer une seule légende combinée.
Résultat : une légende unique a ichant à la fois la barre bleue ventes de glaces et la ligne
rouge Cumul des ventes de glaces, placée en haut à gauche.

Sauvegarde et aƯichage

[Link]("f14/graphique_05.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300


[Link]()

Sauvegarde en PNG puis a ichage classique.

Résultat attendu

Un graphique combiné avec :


• À gauche, une échelle bleue correspondant aux ventes individuelles (les barres bleues).
• À droite, une échelle rouge correspondant au cumul (la courbe rouge croissante).
• En bas, l’axe X commun (les températures).
• Une légende unique en haut à gauche regroupant les deux séries.

Quand utiliser ce type de graphique ?

Le double axe Y est particulièrement utile pour :


• Comparer une valeur brute et sa tendance cumulée (comme ici : ventes vs ventes
cumulées).
• A icher deux grandeurs dans des unités di érentes (ex. température en °C et précipitations
en mm).
• Mettre en relation deux indicateurs liés mais d’échelles incomparables (ex. chi re
d’a aires en milliers d’euros et nombre de clients)
Précaution importante : ce type de graphique peut être trompeur si les échelles sont mal
choisies, car il donne l’illusion que deux courbes se croisent ou s’alignent alors qu’elles n’ont
aucun rapport quantitatif direct. Il convient donc de l’utiliser avec discernement, en s’assurant
que le lecteur comprenne bien qu’il y a deux échelles distinctes, d’où l’importance du code
couleur cohérent entre chaque série et son axe respectif.
Exemples pratiques avec Matplotlib 175

6 - Balisage LaTeX

Dans ce paragraphe, on compose un graphique classique (figure 6), mais avec une particularité
notable : l’utilisation de la syntaxe LaTeX pour a icher des équations mathématiques joliment
formatées dans le titre, les étiquettes, la légende et même dans une boîte de texte annotée
sur le graphique.
Figure n°6

# x contient les entiers de 0 à 5


# y contient les carrés y = x**2  10
abscisses = [Link](0, 5, 6, dtype=int)
print("abscisses =",abscisses)
ordonnees = abscisses ** 2  10
print("ordonnees =",ordonnees)
# graphique
176 Exemples pratiques avec Matplotlib

[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’14’})


# Afficher le graphique avec x & y
fig, ax = [Link](1,1,figsize=(15,10,facecolor=’oldlace’,dpi=300
[Link](abscisses, ordonnees, color=’red’, lw=2.0, label=’équation $y = x^2  10$’,
marker=’o’, markersize=12, markerfacecolor=’dodgerblue’,
markeredgecolor=’black’, markeredgewidth=1.0
# Ajouter un titre
[Link](‘Graphique avec une équation écrite en LaTex \n’ + r’$y = x^2  10$’,
fontsize=22,fontweight=’bold’,y=1.01
# Ajouter un label X & Y
[Link](‘Nombre entier’,color=’red’)
[Link](‘Equation $y = x^2  10$’,labelpad=15,color=’red’)
[Link](loc=’upper left’,facecolor=’whitesmoke’,edgecolor=’black’,labelcolor=’blue’)
[Link](True,color=’gray’,alpha=0.3
[Link](0, 25, ‘équation LaTex\n’ + r’$y = x^2  10$’, fontsize=26, color=’green’,
bbox=dict(facecolor=’oldlace’, alpha=1.0, edgecolor=’blue’, lw=2.0
#plt.tight_layout()
[Link]("f14/graphique_06.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

abscisses = [0 1 2 3 4 5]
ordonnees = [10 11 14 19 26 35]

L’écriture mathématique avec LaTeX

LaTeX est un système de composition de texte particulièrement réputé pour sa capacité à


écrire des formules mathématiques avec une typographie professionnelle (exposants,
indices, fractions, symboles grecs, intégrales, etc). Matplotlib intègre nativement un moteur
LaTeX simplifié appelé mathtext, qui permet d’insérer des formules sans installer LaTeX sur la
machine. Pour activer ce mode dans une chaîne de caractères, il su it d’entourer la formule
de signes dollar $...$. Par exemple :
• ’$y = x^{2}$’ a iche y = x² avec un vrai exposant typographique.
• ’$\alpha + \beta$’ a iche α + β.
• ’$\frac{a}{b}$’ a iche une fraction propre.

Création des données

abscisses = [Link](0, 5, 6, dtype=int)


ordonnees = abscisses**2  10
Exemples pratiques avec Matplotlib 177

Les abscisses sont [0, 1, 2, 3, 4, 5] et les ordonnées calculent y = x² + 10, soit [10, 11, 14, 19,
26, 35].

Configuration globale et création de la figure

[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’14’ })


fig, ax = [Link](1,1,figsize=(15,10,facecolor=’oldlace’,dpi=300

Configuration standard : police Roboto Condensed, taille 14, figure de 15×10 pouces avec
fond oldlace.

Tracé de la courbe avec marqueurs personnalisés

[Link](abscisses, ordonnees, color=’red’, lw=2.0, label=’équation $y = x^2  10$’,


marker=’o’, markersize=12, markerfacecolor=’dodgerblue’,
markeredgecolor=’black’, markeredgewidth=1.0

La courbe rouge est tracée avec des marqueurs circulaires bleus (dodgerblue) cerclés de noir.
Le label de la légende contient la formule $y = x^{2} + 10$ :
• Le ^ indique un exposant.
• Les accolades {2} délimitent ce qui doit être mis en exposant (ici, le chi re 2).
Résultat a iché dans la légende : équation y = x² + 10 avec un vrai 2 en exposant.

Titre avec équation LaTeX et retour à la ligne

[Link](‘Graphique avec une équation écrite en LaTex \n’ + r’$y = x^2  10$’, fontsize=22,
fontweight=’bold’, y=1.01

Ce titre combine deux techniques intéressantes :


• Le retour à la ligne avec \n - Le caractère \n introduit un saut de ligne dans la chaîne. Le
titre s’a iche donc sur deux lignes, ce qui aère la présentation et permet de mettre en
valeur l’équation sur une ligne dédiée.
• La chaîne brute (raw string) avec r’...’ - Le préfixe r devant la chaîne crée une chaîne brute
dans laquelle les antislashs \ sont traités littéralement, sans interprétation. C’est une
précaution utile avec LaTeX, qui utilise massivement le caractère \ (pour \alpha, \frac, \sqrt,
etc). Sans le r, Python pourrait interpréter certaines séquences comme des caractères
spéciaux et provoquer des erreurs.
Astuce - Prenez l’habitude d’utiliser r’...’ devant toute chaîne contenant du LaTeX, même si la
formule courante ne comporte pas d’antislash. Cela évite les mauvaises surprises.
178 Exemples pratiques avec Matplotlib

Étiquettes des axes avec LaTeX

[Link](‘Nombre entier’, color=’red’)


[Link](‘Equation $y = x^2  10$’, labelpad=15, color=’red’)

L’étiquette Y mélange du texte standard et de la formule LaTeX dans la même chaîne. Tout ce
qui est entre $...$ est rendu en mode mathématique, le reste en texte normal. Le paramètre
labelpad=15 ajoute un espacement de 15 points entre l’étiquette et l’axe Y, pour éviter qu’elle
ne colle aux graduations.

Légende et grille

[Link](loc=’upper left’, facecolor=’whitesmoke’, edgecolor=’black’, labelcolor=’blue’)


[Link](True, color=’gray’, alpha=0.3

Configuration standard de la légende (haut gauche, fond whitesmoke) et d’une grille discrète.
La légende a ichera la formule LaTeX du label transmis plus haut.

Annotation avec boîte de texte encadrée

[Link](0, 25, ‘équation LaTex\n’ + r’$y = x^2  10$’, fontsize=26, color=’green’,


bbox=dict(facecolor=’oldlace’, alpha=1.0, edgecolor=’blue’, lw=2.0

C’est une nouveauté importante. La méthode [Link]() permet de placer une boîte de texte
libre n’importe où dans le graphique, avec des coordonnées précises dans le système de
l’axe. Décomposons ses paramètres :
• 0, 25 : coordonnées (x, y) du coin inférieur gauche du texte, en unités du graphique (ici
x=0, y=25).
• Le texte mélange du texte simple (équation LaTex), un retour à la ligne (\n), puis la formule
LaTeX.
• fontsize=26, color=’green’ : texte vert de grande taille.
• bbox=dict(...) : ce dictionnaire définit une boîte (bounding box) autour du texte :
facecolor=’oldlace’ est le fond beige de la boîte. alpha=1.0 spécifie une boîte totalement
opaque (1.0 = 100%). edgecolor=’blue’ spécifie un contour bleu. lw=2.0 spécifie une
épaisseur du contour de 2 pixels.
Résultat : une étiquette encadrée de bleu contenant la formule, positionnée dans la zone du
graphique au niveau (0, 25). C’est très utile pour commenter un graphique, mettre en évidence
une formule ou annoter une zone particulière.
Exemples pratiques avec Matplotlib 179

Sauvegarde et aƯichage

[Link]("f14/graphique_06.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300


[Link]()

Sauvegarde et a ichage classiques.

Résultat attendu

Un graphique avec :
• Une courbe rouge de la parabole décalée (y = x² + 10), avec des points bleus cerclés de
noir.
• Un titre sur deux lignes avec la formule mathématique bien typographiée en dessous.
• Des étiquettes d’axes rouges dont celle de Y contient la formule.
• Une boîte de texte verte encadrée de bleu en bas à gauche du graphique, rappelant
l’équation tracée.

Quelques rappels de syntaxe mathtext / LaTeX

Voici les syntaxes les plus utiles à connaître pour écrire des formules dans Matplotlib.

Syntaxe Résultat

$x^{2}$ exposant : x²

$x_{i}$ indice : x2

$\sqrt{x}$ racine carrée

$\frac{a}{b}$ fraction a/b

$\alpha, \beta, \gamma$ lettres grecques α, β, γ

$\pi, \infty$ symboles π, ∞

$\sum_{i=1}^{n} x_{i}$ somme avec bornes

$\int_{0}^{1} f(x) dx$ intégrale


180 Exemples pratiques avec Matplotlib

Quand utiliser LaTeX dans les graphiques ?

Cette syntaxe est particulièrement précieuse pour :


• Les graphiques scientifiques (physique, mathématiques, statistiques) où les formules
doivent être rigoureusement typographiées.
• Les rapports académiques ou les publications nécessitant une présentation soignée.
• L’enseignement, où l’équation doit apparaître clairement pour accompagner la courbe.
Elle évite les approximations du type y = x^2 (avec un accent circonflexe visible) ou alpha (en
toutes lettres), qui sont peu élégants et parfois ambigus.

7 - Histogrammes

Dans ce paragraphe, on compose un histogramme sophistiqué (figure 7) simulant le lancer


de 5000 paires de dés à 6 faces, avec de nombreuses techniques avancées de visualisation
comme le dégradé de couleurs, la courbe théorique superposée, les lignes de référence
statistiques, les annotations, et l’encadré récapitulatif.

Figure n°7

[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’ })


# Generation des donnees
Exemples pratiques avec Matplotlib 181
[Link](42)
lancers_de_1  [Link](1, 7, 5000
lancers_de_2  [Link](1, 7, 5000
somme_lancers = lancers_de_1  lancers_de_2
# Creation de la figure haute resolution
figure, axe = [Link](figsize=(12, 7, dpi=300, facecolor=’lavender’)
axe.set_facecolor(‘whitesmoke’)
# Histogramme : bornes centrees sur les entiers (1.5, 2.5, ... 12.5
valeurs_bins, bords_bins, patches = [Link](
somme_lancers,
bins=[Link](1.5, 13.5, 1,
density=True,
color=’steelblue’,
edgecolor=’white’,
linewidth=1.5,
alpha=0.85,
zorder=3
)
# Degrade de couleur selon la hauteur des barres
palette = plt.get_cmap(‘viridis’)
valeur_max = valeurs_bins.max()
for valeur, patch in zip(valeurs_bins, patches):
patch.set_facecolor(palette(valeur / valeur_max))
# Annotation des frequences au-dessus de chaque barre
for valeur, bord_gauche in zip(valeurs_bins, bords_bins[:-1]):
[Link](bord_gauche + 0.5, valeur + 0.006, f"{valeur:.3f}",
ha=’center’, va=’bottom’, fontsize=12, fontweight=’bold’, color=’black’)
# Courbe theorique (distribution exacte de la somme de 2 des)
sommes_theoriques = [Link](2, 13
probabilites_theoriques = [Link]([1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 / 36
[Link](sommes_theoriques, probabilites_theoriques,
color=’crimson’, marker=’o’, markersize=8, linewidth=2.2,
linestyle=’--’, label=’Distribution theorique’,
markerfacecolor=’white’, markeredgewidth=2, zorder=5
# Lignes de reference
moyenne_empirique = somme_lancers.mean()
mediane_empirique = [Link](somme_lancers)
182 Exemples pratiques avec Matplotlib

[Link](moyenne_empirique, color=’darkorange’, linestyle=’-’, linewidth=2,


label=f’Moyenne = {moyenne_empirique:.2f}’, zorder=4
[Link](mediane_empirique, color=’darkgreen’, linestyle=’:’, linewidth=2,
label=f’Mediane = {mediane_empirique:.1f}’, zorder=4
# Titres et labels
axe.set_title("Distribution de la somme de 2 dés a 6 faces (5000 lancers)",
fontsize=20, fontweight=’bold’, pad=20, color=’black’)
axe.set_xlabel("Somme des deux dés", fontweight=’semibold’, labelpad=10
axe.set_ylabel("Densité de probabilité", fontweight=’semibold’, labelpad=10
# Graduations centrees sur les entiers
axe.set_xticks(range(2, 13
axe.set_xlim(1.5, 12.5
# Grille discrete en arriere-plan
[Link](True, axis=’y’, linestyle=’--’, alpha=0.4, zorder=0
axe.set_axisbelow(True)
# Epuration des bordures
for position in [‘top’, ‘right’]:
[Link][position].set_visible(False)
[Link][‘left’].set_color(‘red’)
[Link][‘left’].set_linewidth(3.0)
[Link][‘bottom’].set_color(‘red’)
[Link][‘bottom’].set_linewidth(3.0)
# Legende stylisee
[Link](loc=’upper right’, frameon=True, fancybox=True, shadow=True,
framealpha=1.0, edgecolor=’black’, fontsize=12
# Encadre statistique
texte_stats = (f"n = {len(somme_lancers)}\n"
f"Moyenne : {moyenne_empirique:.3f}\n"
f"Ecart-type : {somme_lancers.std():.3f}\n"
f"Min - Max : {somme_lancers.min()} - {somme_lancers.max()}")
[Link](0.98, 0.55, texte_stats,
transform=[Link], fontsize=10, family=’monospace’,
verticalalignment=’top’, horizontalalignment=’right’,
bbox=dict(boxstyle=’round,pad=0.9’, facecolor=’white’, edgecolor=’blue’, alpha=0.9
plt.tight_layout()
[Link]("f14/graphique_07.png",facecolor=’lavender’,bbox_inches=’tight’,dpi=300
[Link]()
Exemples pratiques avec Matplotlib 183

Particularité : l’histogramme avec analyse statistique complète

C’est un exemple typique de graphique statistique enrichi qui combine :


• Une simulation aléatoire (approche fréquentiste).
• Une distribution théorique (approche probabiliste).
• Des indicateurs statistiques (moyenne, médiane, écart-type).
• Un dégradé de couleurs pour visualiser la hauteur des barres.
L’objectif pédagogique : vérifier visuellement que la simulation converge bien vers la
distribution théorique attendue (la fameuse pyramide de la somme de deux dés).

Simulation des lancers

[Link](42)
lancers_de_1  [Link](1, 7, 5000
lancers_de_2  [Link](1, 7, 5000
somme_lancers = lancers_de_1  lancers_de_2

La graine aléatoire : [Link](42) fixe le point de départ du générateur de nombres


aléatoires. Conséquence importante : les résultats sont reproductibles. Quiconque relance
le code obtiendra exactement les mêmes 5000 lancers. C’est essentiel pour l’enseignement
et le débogage.
Les lancers : [Link](1, 7, 5000) génère 5000 entiers aléatoires entre 1 inclus et 7
exclu (donc 1 à 6). On simule ainsi deux dés indépendants, puis on additionne leurs résultats.
La variable somme_lancers contient donc 5000 valeurs comprises entre 2 (1+1) et 12 (6+6).

Création de la figure

figure, axe = [Link](figsize=(12, 7, dpi=300, facecolor=’lavender’)


axe.set_facecolor(‘whitesmoke’)

Figure de 12×7 pouces avec fond lavande à l’extérieur et gris clair à l’intérieur de la zone de
tracé. Ce contraste délimite visuellement la zone graphique.

L’histogramme avec bornes centrées

# histogramme
valeurs_bins, bords_bins, patches = [Link](
somme_lancers,
bins=[Link](1.5, 13.5, 1,
184 Exemples pratiques avec Matplotlib

density=True,
color=’steelblue’,
edgecolor=’white’,
linewidth=1.5,
alpha=0.85,
zorder=3
)

Plusieurs points techniques intéressants :


• Les bornes décalées : [Link](1.5, 13.5, 1) crée les limites [1.5, 2.5, 3.5, ..., 12.5].
Pourquoi ce décalage ? Parce qu’on veut centrer chaque barre sur un entier. La barre
correspondant à la somme 7 s’étend de 6.5 à 7.5. Sans ce décalage, les valeurs entières
tomberaient entre deux barres, créant une ambiguïté visuelle.
• density=True : les hauteurs a ichées ne sont pas des e ectifs bruts, mais des densités de
probabilité. Chaque valeur est divisée par le nombre total et par la largeur de la classe,
de telle sorte que l’aire totale de l’histogramme vaut 1. C’est nécessaire pour pouvoir
comparer avec la courbe théorique (qui représente aussi des probabilités).
La déstructuration avec hist() qui renvoie trois objets :
• valeurs_bins : les hauteurs calculées pour chaque barre.
• bords_bins : les positions des bornes (une de plus que le nombre de barres).
• patches : les objets graphiques représentant chaque barre, accessibles individuellement
pour personnalisation.

Dégradé de couleurs selon la hauteur

palette = plt.get_cmap(‘viridis’)
valeur_max = valeurs_bins.max()
for valeur, patch in zip(valeurs_bins, patches):
patch.set_facecolor(palette(valeur / valeur_max))

Cette boucle colore chaque barre individuellement selon sa hauteur. La technique :


• plt.get_cmap(‘viridis’) récupère la palette de couleurs viridis (dégradé violet → bleu → vert
→ jaune).
• Pour chaque barre, on calcule le ratio valeur / valeur_max, donnant un nombre entre 0 et 1.
• On applique ce ratio à la palette : les petites barres tirent vers le violet, les grandes vers
le jaune.
Le résultat met visuellement en évidence le sommet de la distribution (la valeur 7, la plus
probable) par une couleur vive, tandis que les extrêmes (2 et 12) apparaissent en teintes
sombres.
Exemples pratiques avec Matplotlib 185

Annotation des fréquences sur chaque barre

for valeur, bord_gauche in zip(valeurs_bins, bords_bins[:-1]):


[Link](bord_gauche + 0.5, valeur + 0.006,
f"{valeur:.3f}",
ha=’center’, va=’bottom’,
fontsize=12, fontweight=’bold’, color=’black’)

Cette boucle ajoute le chi re de la densité au-dessus de chaque barre. Quelques subtilités :
• bords_bins[:-1] : on prend tous les bords sauf le dernier, puisqu’on veut un texte par barre
(et il y a n+1 bords pour n barres).
• bord_gauche + 0.5 : on décale de 0.5 vers la droite pour centrer le texte sur la barre.
• valeur + 0.006 : on place le texte légèrement au-dessus de la barre.
• f"{valeur:.3f}" : formatage à 3 décimales.
• ha=’center’, va=’bottom’ : alignement horizontal au centre et vertical sur la base du texte.

Superposition de la distribution théorique

sommes_theoriques = [Link](2, 13


probabilites_theoriques = [Link]([1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 / 36
[Link](sommes_theoriques, probabilites_theoriques,
color=’crimson’, marker=’o’, markersize=8, linewidth=2.2,
linestyle=’--’, label=’Distribution theorique’,
markerfacecolor=’white’, markeredgewidth=2, zorder=5

C’est un point clé pédagogique du graphique. Pour deux dés, il existe 36 combinaisons
possibles (6×6), et la probabilité de chaque somme suit une distribution triangulaire :
• Somme 2 : 1 combinaison (1+1) → 1/36
• Somme 7 : 6 combinaisons (1+6, 2+5, 3+4, 4+3, 5+2, 6+1) → 6/36
• Somme 12 : 1 combinaison (6+6) → 1/36
La courbe rouge en tirets avec des cercles à cœur blanc trace cette distribution parfaite.
Comparer les barres de l’histogramme à cette courbe permet de visualiser à quel point la
simulation se rapproche de la théorie. Avec 5000 lancers, la correspondance devrait être
excellente.

Lignes de référence verticales

moyenne_empirique = somme_lancers.mean()
mediane_empirique = [Link](somme_lancers)
186 Exemples pratiques avec Matplotlib

[Link](moyenne_empirique, color=’darkorange’, linestyle=’-’, linewidth=2,


label=f’Moyenne = {moyenne_empirique:.2f}’, zorder=4
[Link](mediane_empirique, color=’darkgreen’, linestyle=’:’, linewidth=2,
label=f’Mediane = {mediane_empirique:.1f}’, zorder=4

La méthode axvline() (axis vertical line) trace une ligne verticale qui traverse tout le graphique.
On l’utilise ici pour marquer :
• La moyenne empirique en orange (trait plein).
• La médiane empirique en vert foncé (pointillés).
Théoriquement, pour deux dés, moyenne et médiane valent toutes deux 7. Les lignes
devraient donc se superposer très près de cette valeur centrale. Les valeurs numériques sont
directement intégrées dans les labels via la f-string (f’Moyenne = {moyenne_empirique:.2f}’).
À noter qu’il existe aussi axhline() pour les lignes horizontales.

Graduations, grille et axes

axe.set_xticks(range(2, 13
axe.set_xlim(1.5, 12.5
[Link](True, axis=’y’, linestyle=’--’, alpha=0.4, zorder=0
axe.set_axisbelow(True)

set_xticks(range(2, 13)) impose les graduations X uniquement sur les entiers de 2 à 12. set_
xlim() fixe les limites de l’axe X, de sorte que le graphique commence exactement à 1.5 et finit
à 12.5 (bordure des barres extrêmes).
La grille est tracée uniquement sur l’axe Y (axis=’y’), en tirets discrets. set_axisbelow(True)
est une astuce importante : elle force la grille à passer sous les barres pour éviter qu’elle ne
vienne zébrer visuellement les éléments principaux.

Personnalisation des bordures (spines)

for position in [‘top’, ‘right’]:


[Link][position].set_visible(False)
[Link][‘left’].set_color(‘red’)
[Link][‘left’].set_linewidth(3.0)
[Link][‘bottom’].set_color(‘red’)
[Link][‘bottom’].set_linewidth(3.0)

Les spines sont les quatre bordures (haut, bas, gauche, droite) qui encadrent la zone de tracé.
Ici :
Exemples pratiques avec Matplotlib 187
• Les bordures haut et droite sont masquées (style épuré moderne, très courant en
visualisation de données).
• Les bordures gauche et bas sont épaissies (3 pixels) et colorées en rouge.
Ce choix crée un e et de L rouge qui attire le regard sur les axes de référence, tout en allégeant
visuellement l’ensemble.

Légende stylisée

[Link](loc=’upper right’, frameon=True, fancybox=True, shadow=True,


framealpha=1.0, edgecolor=’black’, fontsize=12

Options intéressantes :
• fancybox=True : coins arrondis sur le cadre de la légende.
• shadow=True : ombre portée derrière la légende, pour un e et de relief.
• framealpha=1.0 : totalement opaque.

Encadré statistique avec coordonnées relatives

texte_stats = (f"n = {len(somme_lancers)}\n"


f"Moyenne : {moyenne_empirique:.3f}\n"
f"Ecart-type : {somme_lancers.std():.3f}\n"
f"Min - Max : {somme_lancers.min()} - {somme_lancers.max()}")
[Link](0.98, 0.55, texte_stats,
transform=[Link],
fontsize=10, family=’monospace’,
verticalalignment=’top’, horizontalalignment=’right’,
bbox=dict(boxstyle=’round,pad=0.9’, facecolor=’white’,
edgecolor=’blue’, alpha=0.9

Plusieurs techniques avancées sont à l’œuvre :


• Le texte multi-lignes construit avec des f-strings et des \n regroupe 4 statistiques clés :
e ectif, moyenne, écart-type et plage min-max.
• transform=[Link] est un point très important : ce paramètre change le système de
coordonnées utilisé par text(). Sans lui, les coordonnées (0.98, 0.55) seraient interprétées
dans les unités du graphique (donc presque à l’origine, là où les barres sont hautes). Avec
transAxes, les coordonnées deviennent relatives à la zone de tracé. (0, 0) correspond au
coin inférieur gauche de la zone. (1, 1) correspond au coin supérieur droit de la zone.
(0.98, 0.55) signifie donc à 98% de la largeur, à 55% de la hauteur.
• C’est très pratique pour placer un encadré à une position stable, indépendante des
valeurs tracées.
188 Exemples pratiques avec Matplotlib

• boxstyle=’round,pad=0.9’ définit le style du cadre : coins arrondis avec un rembourrage


interne (padding) de 0.9 autour du texte.
• family=’monospace’ applique une police à chasse fixe (type courrier/terminal) : chaque
caractère occupe la même largeur, ce qui aligne verticalement les valeurs numériques,
améliorant la lisibilité d’un bloc statistique.

Sauvegarde et aƯichage

plt.tight_layout()
[Link]("f14/graphique_07.png", facecolor=’lavender’, bbox_inches=’tight’, dpi=300
[Link]()

plt.tight_layout() ajuste automatiquement les marges pour éviter que les éléments ne se
chevauchent ou ne débordent.

Résultat attendu

Un histogramme richement annoté, où l’on devrait observer :


• Une forme triangulaire culminant à la valeur 7.
• Les barres les plus hautes (vers 7) en jaune-vert, les plus basses (2 et 12) en violet sombre.
• La courbe théorique rouge en tirets épousant presque parfaitement le sommet des barres.
• Les lignes moyenne et médiane quasi superposées sur la valeur 7.
• Un encadré statistique en haut à droite confirmant des valeurs proches des attentes
théoriques (moyenne ≈ 7, écart-type ≈ 2.42).

Conclusion : un graphique "tout-terrain"

Ce code illustre parfaitement comment combiner plusieurs couches d’information dans un


seul graphique :
• Les données brutes (histogramme).
• Leur encodage visuel (dégradé de couleurs selon hauteur).
• Les annotations précises (valeurs au-dessus de chaque barre).
• Un modèle de référence (courbe théorique).
• Des indicateurs statistiques (moyenne, médiane, encadré).
• Une mise en forme soignée (spines épurés, légende avec ombre, coordonnées relatives).
C’est un exemple complet particulièrement utile pour des rapports d’analyse, des supports
pédagogiques en statistiques, ou toute communication où l’on veut à la fois montrer les
données et convaincre par la rigueur de l’analyse.
Attention cependant, une telle densité d’information demande un lecteur attentif. Dans
d’autres contextes, une version plus épurée pourrait être préférable.
Exemples pratiques avec Matplotlib 189

8 - Diagrammes en barres

Dans ce paragraphe, on compose un diagramme en barres empilées (stacked bar chart)


comparant la répartition hommes/femmes dans quatre niveaux d’enseignement (figure
8). Chaque barre représente 100 % et est divisée en deux segments superposés, avec des
annotations détaillées à l’intérieur.
Figure n°8

[Link]({‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’})


# Donnees
types_enseignants = [‘Maternelle’, ‘Elementaire’, ‘Secondaire’, ‘Specialise’]
enseignants_hommes = [Link]([12, 20, 44, 14
enseignants_femmes = [Link]([88, 80, 56, 86
indices_enseignants = [Link](len(types_enseignants))
# Palette professionnelle (contrastee, accessible daltonisme)
couleur_femmes = ‘crimson’ # rouge
couleur_hommes = ‘mediumblue’ # bleu
# Creation de la figure haute resolution
190 Exemples pratiques avec Matplotlib

figure, axe = [Link](figsize=(11, 7, dpi=300, facecolor=’oldlace’)


axe.set_facecolor(‘whitesmoke’)
# Barres empilees : femmes en bas (valeurs majoritaires)
largeur_barre = 0.55
barres_femmes = [Link](indices_enseignants, enseignants_femmes,
width=largeur_barre, label=’Femmes’,
color=couleur_femmes, edgecolor=’black’, linewidth=1.0,
zorder=3
barres_hommes = [Link](indices_enseignants, enseignants_hommes,
width=largeur_barre, label=’Hommes’,
bottom=enseignants_femmes,
color=couleur_hommes, edgecolor=’black’, linewidth=1.0,
zorder=3
# Annotations : pourcentages a l’interieur de chaque segment
for indice, (valeur_f, valeur_h) in enumerate(zip(enseignants_femmes, enseignants_hommes)):
[Link](indice, valeur_f / 2, f"{valeur_f}%",
ha=’center’, va=’center’, fontsize=14, fontweight=’bold’, color=’white’, zorder=5
[Link](indice, valeur_f + valeur_h / 2, f"{valeur_h}%",
ha=’center’, va=’center’, fontsize=14, fontweight=’bold’, color=’white’, zorder=5
# Total au-dessus de chaque barre
for indice, (valeur_f, valeur_h) in enumerate(zip(enseignants_femmes, enseignants_hommes)):
total = valeur_f + valeur_h
[Link](indice, total + 2, f"Total : {total}%",
ha=’center’, va=’bottom’, fontsize=10, fontweight=’semibold’, color=’#333333’)
# Titre et labels
axe.set_title("Repartition hommes/femmes dans l’enseignement par niveau",
fontsize=20, fontweight=’bold’, pad=20, color=’black’)
axe.set_xlabel("Niveau d’enseignement", fontweight=’bold’, labelpad=10
axe.set_ylabel("Pourcentage (%", fontweight=’bold’, labelpad=10
# Graduations personnalisees
axe.set_xticks(indices_enseignants)
axe.set_xticklabels(types_enseignants, fontsize=11, color=’navy’)
axe.set_ylim(0, 115
axe.set_yticks(range(0, 101, 20
# Grille horizontale discrete
[Link](True, axis=’y’, linestyle=’--’, alpha=0.4, zorder=0
axe.set_axisbelow(True)
Exemples pratiques avec Matplotlib 191
# Epuration et stylisation des bordures
for position in [‘top’, ‘right’]:
[Link][position].set_visible(False)
for position in [‘left’, ‘bottom’]:
[Link][position].set(color=’grey’, linewidth=1.5
# Legende stylisee avec titre
legende = [Link](loc=’center’, frameon=True, fancybox=True, shadow=True, ncols=2,
fontsize=11, framealpha=1.0, edgecolor=’green’, facecolor=’white’,
title=’Catégorie’, title_fontsize=11, bbox_to_anchor=(0.5, 0.0, 0.0, 0.50
legende.get_title().set_fontweight(‘bold’)
# Source discrete en bas
[Link](0.01, 0.12,
"Données illustratives - Graphique généré avec Matplotlib",
transform=[Link], fontsize=8, style=’italic’, color=’grey’)
plt.tight_layout()
[Link]("f14/graphique_08.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

Particularité : le diagramme à barres empilées à 100 %

C’est la grande nouveauté de ce graphique. Contrairement aux barres simples qui représentent
des valeurs indépendantes, les barres empilées décomposent une même valeur totale en
plusieurs sous-catégories. Ici, chaque barre totalise 100 % et est scindée en deux parties
pour visualiser les femmes (en bas) et les hommes (en haut). Ce type de représentation est
particulièrement e icace pour :
• Visualiser une composition (parts de chaque catégorie dans un tout).
• Comparer ces compositions entre plusieurs groupes (ici, les niveaux d’enseignement).
• Mettre en évidence des déséquilibres (ici, une féminisation marquée du métier, plus ou
moins forte selon le niveau).

Préparation des données

types_enseignants = [‘Maternelle’, ‘Elementaire’, ‘Secondaire’, ‘Specialise’]


enseignants_hommes = [Link]([12, 20, 44, 14
enseignants_femmes = [Link]([88, 80, 56, 86
indices_enseignants = [Link](len(types_enseignants))

Quatre niveaux d’enseignement, avec les pourcentages correspondants pour les hommes
192 Exemples pratiques avec Matplotlib

et les femmes. On remarque que chaque paire totalise bien 100 % (12+88, 20+80, etc). La
variable indices_enseignants = [Link](4) génère [0, 1, 2, 3], des positions numériques sur
l’axe X. Ces indices servent à placer les barres à intervalles réguliers. Les étiquettes textuelles
viendront les remplacer visuellement plus tard.

Palette de couleurs accessible

couleur_femmes = ‘crimson’ # rouge


couleur_hommes = ‘mediumblue’ # bleu

Le commentaire mentionne une palette accessible au daltonisme. Le choix du rouge et du


bleu (ou plus précisément crimson et mediumblue) est délibéré : ces deux couleurs di èrent
su isamment en luminosité et en teinte pour rester distinguables par la plupart des personnes
atteintes de daltonisme. Un choix du type rouge/vert serait au contraire problématique.

Création de la figure

figure, axe = [Link](figsize=(11, 7, dpi=300, facecolor=’oldlace’)


axe.set_facecolor(‘whitesmoke’)

Figure de 11×7 pouces, fond oldlace à l’extérieur et whitesmoke à l’intérieur.

L’empilement des barres : le mécanisme clé

# empilement des barres


largeur_barre = 0.55
barres_femmes = [Link](indices_enseignants, enseignants_femmes,
width=largeur_barre, label=’Femmes’,
color=couleur_femmes, edgecolor=’black’, linewidth=1.0,
zorder=3
barres_hommes = [Link](indices_enseignants, enseignants_hommes,
width=largeur_barre, label=’Hommes’,
bottom=enseignants_femmes,
color=couleur_hommes, edgecolor=’black’, linewidth=1.0,
zorder=3

Le paramètre bottom=enseignants_femmes est le cœur de l’empilement. Décomposons la


logique :
• La première série (femmes) est tracée de façon classique, depuis y=0. Les barres montent
respectivement à 88, 80, 56 et 86.
Exemples pratiques avec Matplotlib 193
• La seconde série (hommes) est tracée avec bottom=enseignants_femmes, ce qui signifie
que chaque barre démarre non pas à zéro, mais au sommet de la barre correspondante
de la première série. La barre rouge Maternelle monte à 88 → la barre bleue Maternelle
commence à 88 et monte jusqu’à 88+12=100.
C’est ce décalage qui crée l’e et d’empilement. Le paramètre bottom peut accepter un simple
nombre (toutes les barres décalent de la même façon) ou un tableau de valeurs (chaque barre
décale di éremment), comme ici.
Le paramètre width=0.55 définit la largeur des barres (55% de l’intervalle disponible entre
deux positions). Une largeur inférieure à 1 laisse visuellement respirer chaque barre.

Annotations à l’intérieur des segments

for indice, (valeur_f, valeur_h) in enumerate(zip(enseignants_femmes, enseignants_hommes)):


[Link](indice, valeur_f / 2, f"{valeur_f}%",
ha=’center’, va=’center’,
fontsize=14, fontweight=’bold’, color=’white’, zorder=5
[Link](indice, valeur_f + valeur_h / 2, f"{valeur_h}%",
ha=’center’, va=’center’,
fontsize=14, fontweight=’bold’, color=’white’, zorder=5

Cette boucle place un texte blanc gras au centre de chaque segment coloré. Le calcul des
positions verticales est astucieux :
• valeur_f / 2 : pour le segment des femmes (qui va de 0 à valeur_f), le milieu vertical se situe
à moitié de cette valeur.
• valeur_f + valeur_h / 2 : pour le segment des hommes (qui va de valeur_f à valeur_f +
valeur_h), le milieu vertical se situe à valeur_f + moitié de valeur_h.
Les paramètres ha=’center’, va=’center’ (alignement horizontal et vertical) centrent le texte sur
les coordonnées fournies. La couleur blanche du texte contraste avec les fonds colorés pour
rester lisible. La fonction enumerate(zip(...)) permet d’itérer simultanément sur l’indice et sur
les deux tableaux appairés.

Totaux au-dessus de chaque barre

for indice, (valeur_f, valeur_h) in enumerate(zip(enseignants_femmes, enseignants_hommes)):


total = valeur_f + valeur_h
[Link](indice, total + 2, f"Total : {total}%",
ha=’center’, va=’bottom’, fontsize=10, fontweight=’semibold’, color=’gray’)

Cette seconde boucle ajoute Total : 100% au-dessus de chaque barre, à 2 unités au-dessus
194 Exemples pratiques avec Matplotlib

du sommet. La couleur ’gray’ est un gris foncé, une nuance élégante, moins agressive qu’un
noir pur.

Graduations personnalisées

axe.set_xticks(indices_enseignants)
axe.set_xticklabels(types_enseignants, fontsize=11, color=’navy’)
axe.set_ylim(0, 115
axe.set_yticks(range(0, 101, 20

Le remplacement des indices par des étiquettes textuelles : set_xticks() fixe les positions des
graduations (aux indices 0, 1, 2, 3), puis set_xticklabels() leur associe des libellés textuels
en bleu marine. C’est le mécanisme standard pour transformer un axe numérique en axe
catégoriel.
set_ylim(0, 115) fixe l’axe Y à la plage 0–115, laissant un peu d’espace au-dessus du 100 pour
que les annotations Total : 100% ne débordent pas.
set_yticks(range(0, 101, 20)) n’a iche les graduations que de 0 à 100, tous les 20, même si l’axe
monte jusqu’à 115. Cela évite d’a icher une graduation 120 qui serait trompeuse (puisque les
données sont des pourcentages).

Grille et bordures stylisées

[Link](True, axis=’y’, linestyle=’--’, alpha=0.4, zorder=0


axe.set_axisbelow(True)
for position in [‘top’, ‘right’]:
[Link][position].set_visible(False)
for position in [‘left’, ‘bottom’]:
[Link][position].set(color=’grey’, linewidth=1.5

La grille horizontale en tirets facilite la lecture des pourcentages. set_axisbelow(True) place la


grille sous les barres pour éviter le zébrage visuel. Les bordures haut et droite sont masquées
(style épuré moderne). Les bordures gauche et bas sont colorées en gris et légèrement
épaissies, dans un style sobre.

Légende avec titre et positionnement avancé

legende = [Link](loc=’center’, frameon=True, fancybox=True, shadow=True, ncols=2,


fontsize=11, framealpha=1.0, edgecolor=’green’, facecolor=’white’,
title=’Catégorie’, title_fontsize=11, bbox_to_anchor=(0.5, 0.0, 0.0, 0.50
Exemples pratiques avec Matplotlib 195
legende.get_title().set_fontweight(‘bold’)

Cette légende cumule plusieurs techniques avancées :


• ncols=2 organise les entrées sur 2 colonnes au lieu d’une seule verticale : Femmes et
Hommes s’a ichent côte à côte. C’est plus compact et plus élégant quand il n’y a que
deux catégories.
• title=’Catégorie’ ajoute un titre à la légende (au-dessus des entrées). L’instruction legende.
get_title().set_fontweight(‘bold’) accède ensuite à l’objet titre pour le mettre en gras.
• bbox_to_anchor=(0.5, 0.0, 0.0, -0.50) est un paramètre puissant mais délicat : il permet
d’ancrer la légende à un point spécifique en dehors de la zone de tracé, en coordonnées
relatives. Ici, la légende est placée sous le graphique, ce qui libère de l’espace à l’intérieur
pour les données.
• fancybox=True, shadow=True produisent des coins arrondis et une ombre portée, pour un
e et de relief. La bordure verte (edgecolor=’green’) encadre la légende.

Mention de source discrète

[Link](0.01, 0.12,
"Données illustratives - Graphique généré avec Matplotlib",
transform=[Link], fontsize=8, style=’italic’, color=’grey’)

C’est une bonne pratique professionnelle : mentionner la source des données ou la nature du
graphique. L’utilisation de transform=[Link] place le texte en coordonnées relatives à
la zone de tracé : (0.01, -0.12) signifie légèrement à droite du bord gauche, 12 % en dessous du
bord inférieur. Le style italique gris clair et la petite taille rendent cette mention discrète sans
l’e acer complètement.

Sauvegarde et aƯichage

# affichage
plt.tight_layout()
[Link]("f14/graphique_08.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300
[Link]()

Ajustement automatique des marges, puis sauvegarde et a ichage.

Résultat attendu

Un graphique professionnel avec :


• Quatre barres empilées représentant chacune 100 %, avec la partie femmes en rouge
(majoritaire partout) et la partie hommes en bleu.
196 Exemples pratiques avec Matplotlib

• Des annotations blanches au centre de chaque segment indiquant le pourcentage.


• Le total 100 % a iché au-dessus de chaque barre.
• Une légende soignée sous le graphique, avec titre Catégorie.
• Des bordures épurées (haut et droite masquées).
• Une mention discrète de la source en bas.

Lecture du graphique
On observe que la profession enseignante est fortement féminisée à tous les niveaux, avec
des nuances :
• 88 % de femmes en maternelle (très féminisé).
• 80 % en élémentaire.
• 56 % au secondaire (niveau le plus équilibré, avec 44 % d’hommes).
• 86 % dans le spécialisé.
Le secondaire se distingue nettement comme le seul niveau où la proportion d’hommes
dépasse 20 %, ce qui correspond à une tendance socio-professionnelle réelle dans beaucoup
de pays.

Quand utiliser les barres empilées ?


Ce type de graphique est idéal quand :
• On veut visualiser la composition d’un tout (les pourcentages totalisent 100 %).
• On compare plusieurs groupes sur cette même composition.
• Le nombre de catégories est limité (2 à 4 idéalement, au-delà, la lecture devient vite
confuse).
Limites à connaître :
• Di icile de comparer les segments intermédiaires entre barres (seuls les segments du
bas partagent la même base de référence).
• Avec beaucoup de catégories, les couleurs et la lisibilité se dégradent rapidement.
• Pour comparer des valeurs absolues (non des pourcentages), il vaut souvent mieux
privilégier des barres côte à côte (grouped bar chart).
Dans ce cas précis, les barres empilées à 100 % sont un choix pertinent car l’information
principale est bien la répartition interne (femmes vs hommes) au sein de chaque niveau
d’enseignement.

9 - Diagrammes circulaires

Dans ce paragraphe, on compose un diagramme en anneau (donut chart) représentant la


répartition des Pokémon selon leurs 18 types, avec les couleurs o icielles de la franchise,
des segments décalés pour mettre en évidence les trois plus gros types, un total au centre et
une légende détaillée à droite (figure 9).
Exemples pratiques avec Matplotlib 197
Figure n°9

import [Link] as peffects


[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’ })
# Donnees
types_pokemon = [‘Eau’, ‘Normal’, ‘Vol’, ‘Plante’, ‘Psy’, ‘Insecte’, ‘Feu’, ‘Poison’,
‘Sol’, ‘Roche’, ‘Combat’, ‘Tenebres’, ‘Acier’, ‘Electrik’, ‘Dragon’, ‘Fee’, ‘Spectre’, ‘Glace’]
nombres_pokemon = [133, 109, 101, 98, 85, 77, 68, 66, 65, 60, 57, 54, 53, 51, 50, 50, 46, 40
# Couleurs OFFICIELLES des types Pokemon (codes issus de la franchise)
couleurs_types = {
‘Eau’: ‘#6890F0’, ‘Normal’: ‘#A8A878’, ‘Vol’: ‘#A890F0’, ‘Plante’: ‘#78C850’,
‘Psy’: ‘#F85888’, ‘Insecte’: ‘#A8B820’, ‘Feu’: ‘#F08030’, ‘Poison’: ‘#A040A0’,
‘Sol’: ‘#E0C068’, ‘Roche’: ‘#B8A038’, ‘Combat’: ‘#C03028’, ‘Tenebres’: ‘#705848’,
‘Acier’: ‘#B8B8D0’, ‘Electrik’: ‘#F8D030’, ‘Dragon’: ‘#7038F8’, ‘Fee’: ‘#EE99AC’,
‘Spectre’: ‘#705898’, ‘Glace’: ‘#98D8D8’
}
liste_couleurs = [couleurs_types[type_pokemon] for type_pokemon in types_pokemon]
198 Exemples pratiques avec Matplotlib

# Accentuation des 3 plus gros segments


decalages = [0 * 18
decalages[0]  0.08
decalages[1]  0.04
decalages[2]  0.02
# Calcul du total et des labels detailles pour la legende
total_pokemon = sum(nombres_pokemon)
labels_legende = [f"{type_pkm} - {nb} ({nb/total_pokemon*100.1f}%)"
for type_pkm, nb in zip(types_pokemon, nombres_pokemon)]
# Creation de la figure haute resolution
figure = [Link](figsize=(13, 9, dpi=300, facecolor=’lavender’)
axes_pie = figure.add_axes([0.02, 0.08, 0.55, 0.82
# Diagramme en anneau (donut) pour un aspect moderne
parts, textes, textes_auto = axes_pie.pie(
nombres_pokemon,
explode=decalages,
labels=types_pokemon,
colors=liste_couleurs,
autopct=’%1.1f%%’,
startangle=90,
pctdistance=0.80,
labeldistance=1.08,
wedgeprops=dict(width=0.45, edgecolor=’white’, linewidth=2,
textprops=dict(fontsize=12, fontweight=’bold’, color=’black’)
)
# Pourcentages en blanc avec contour noir (lisibles sur toutes les couleurs)
for texte_auto in textes_auto:
texte_auto.set_color(‘white’)
texte_auto.set_fontsize(12)
texte_auto.set_fontweight(‘bold’)
# Total au centre de l’anneau
axes_pie.text(0, 0.08, f"{total_pokemon}", ha=’center’, va=’center’,
fontsize=32, fontweight=’bold’, color=’black’)
axes_pie.text(0, 0.10, "Pokemon", ha=’center’, va=’center’, fontsize=13, color=’grey’, style=’italic’)
# Titre et sous-titre
[Link]("Répartition des Pokemon par type", fontsize=22, fontweight=’bold’, y=0.96, color=’navy’)
[Link](0.5, 0.91, "Nombre de Pokemon recensés pour chacun des 18 types",
Exemples pratiques avec Matplotlib 199
ha=’center’, fontsize=12, style=’italic’, color=’red’)
# Legende detaillee dans sa propre zone a droite
axes_legende = figure.add_axes([0.62, 0.08, 0.35, 0.82
axes_legende.set_axis_off()
legende = axes_legende.legend(
parts, labels_legende,
loc=’center left’,
frameon=True, fancybox=True, shadow=False, facecolor=’white’,
fontsize=10, framealpha=1.0, edgecolor=’black’,
title=’Type - Effectif (%’, title_fontsize=11,
handlelength=1.5, handleheight=1.2
)
legende.get_title().set_fontweight(‘bold’)
# Source discrete
[Link](0.02, 0.02, "Données illustratives - Graphique généré avec Matplotlib",
fontsize=12, style=’italic’, color=’grey’)
[Link]("f14/graphique_09.png",facecolor=’lavender’,bbox_inches=’tight’,dpi=300
[Link]()

Particularité : le diagramme en anneau (donut)

C’est la grande nouveauté de ce graphique. Un donut chart est une variante du camembert
(pie chart) dans laquelle le centre est évidé. Cette simple modification apporte plusieurs
avantages :
• L’espace central libre peut accueillir une information clé (ici, le total global).
• L’aspect moderne et épuré est privilégié dans les tableaux de bord contemporains.
• La lecture se fait par la longueur d’arc plutôt que par la surface, ce qui serait en théorie
plus perceptible (même si la di érence reste débattue parmi les spécialistes de la data
viz).
Techniquement, Matplotlib ne propose pas de fonction donut() dédiée : on utilise la fonction
pie() classique avec un paramètre spécial qui évide le centre. C’est une astuce élégante.

Préparation des données

types_pokemon = [‘Eau’, ‘Normal’, ‘Vol’, ‘Plante’, ...]


nombres_pokemon = [133, 109, 101, 98, ...]

Dix-huit types de Pokémon, chacun associé à un e ectif. Les données sont déjà triées par
200 Exemples pratiques avec Matplotlib

ordre décroissant, ce qui est une bonne pratique pour un diagramme circulaire : les plus
grosses parts apparaîtront en premier après la rotation initiale, facilitant la lecture.

Couleurs oƯicielles via dictionnaire

couleurs_types = {
‘Eau’: ‘#6890F0’, ‘Normal’: ‘#A8A878’, ‘Vol’: ‘#A890F0’, ...
}
liste_couleurs = [couleurs_types[type_pokemon] for type_pokemon in types_pokemon]

Le dictionnaire associe chaque type à son code couleur hexadécimal o iciel issu de la
franchise. C’est une excellente pratique : les joueurs reconnaîtront instantanément le bleu
de Eau, le rouge de Combat, le jaune de Électrik, etc. Respecter les conventions visuelles d’un
univers familier améliore la lisibilité immédiate du graphique.
La compréhension de liste [couleurs_types[t] for t in types_pokemon] génère une liste de
couleurs dans le même ordre que les types. Cet ordre est crucial : Matplotlib applique les
couleurs aux parts du diagramme dans leur ordre d’apparition.

Décalage (explode) des trois plus gros segments

decalages = [0 * 18
decalages[0]  0.08
decalages[1]  0.04
decalages[2]  0.02

Le paramètre explode permet de détacher certaines parts du centre du camembert, pour les
mettre en valeur. Ici :
• Le type Eau (le plus nombreux) est décalé de 0.08 unité.
• Normal de 0.04.
• Vol de 0.02.
Le décalage dégressif crée un e et de hiérarchie visuelle élégant : le plus gros segment est le
plus détaché, les suivants le sont moins. Tous les autres restent collés au centre. L’initialisation
[0] * 18 crée une liste de 18 zéros, puis on modifie uniquement les trois premiers indices.

Labels de légende enrichis

total_pokemon = sum(nombres_pokemon)
labels_legende = [f"{type_pkm} - {nb} ({nb/total_pokemon*100.1f}%)"
for type_pkm, nb in zip(types_pokemon, nombres_pokemon)]
Exemples pratiques avec Matplotlib 201
Cette compréhension de liste génère des libellés du type Eau - 133 (11.1%) combinant trois
informations en une seule ligne :
• Le nom du type.
• Le nombre absolu.
• Le pourcentage calculé dynamiquement.
Le format :.1f limite le pourcentage à une décimale. La fonction zip() permet de parcourir
simultanément les deux listes appariées.

Création d’une figure avec zones personnalisées

figure = [Link](figsize=(13, 9, dpi=300, facecolor=’lavender’)


axes_pie = figure.add_axes([0.02, 0.08, 0.55, 0.82

La méthode add_axes() est une nouveauté importante dans ce code. Contrairement à


subplots() qui crée des grilles automatiques de sous-graphiques, add_axes() permet de
placer manuellement une zone de tracé en spécifiant ses coordonnées exactes sous la forme
[gauche, bas, largeur, hauteur], toutes exprimées en coordonnées relatives à la figure (de 0 à
1). Ici, [0.02, 0.08, 0.55, 0.82] signifie :
• Gauche à 2 % du bord gauche.
• Bas à 8 % du bord inférieur.
• Largeur de 55 % de la figure.
• Hauteur de 82 % de la figure.
Cela laisse de la place à droite pour une seconde zone qui accueillera la légende. Cette
approche est nécessaire ici parce qu’on veut deux zones de tailles très di érentes (une
grande pour le donut, une plus étroite pour la légende), ce que subplots() ne permet pas aussi
finement.

Le diagramme en anneau

parts, textes, textes_auto = axes_pie.pie(


nombres_pokemon,
explode=decalages,
labels=types_pokemon,
colors=liste_couleurs,
autopct=’%1.1f%%’,
startangle=90,
pctdistance=0.80,
labeldistance=1.08,
wedgeprops=dict(width=0.45, edgecolor=’white’, linewidth=2,
202 Exemples pratiques avec Matplotlib

textprops=dict(fontsize=12, fontweight=’bold’, color=’black’)


)

Plusieurs paramètres méritent un éclairage. La déstructuration en trois variables par la


fonction pie() renvoie trois éléments :
• parts : les objets graphiques des segments (les tranches du camembert).
• textes : les libellés textuels (noms des types autour du donut).
• textes_auto : les pourcentages a ichés automatiquement grâce à autopct.
startangle=90 fait démarrer le premier segment à 90 degrés (en haut du cercle) plutôt qu’à 0 (à
droite). C’est la convention visuelle la plus courante pour les camemberts, correspondant à
la position midi d’une horloge.
autopct=’%1.1f%%’ active l’a ichage automatique des pourcentages sur chaque part. Le
format %1.1f%% signifie : un nombre à virgule avec 1 décimale, suivi d’un signe %. Le double
%% est nécessaire car % est un caractère spécial en formatage, il faut le doubler pour
l’a icher littéralement.
pctdistance=0.80 positionne les pourcentages à 80 % du rayon (donc à l’intérieur de l’anneau).
labeldistance=1.08 place les noms des types à 108 % du rayon (donc à l’extérieur du donut).
Le paramètre clé wedgeprops contient l’instruction qui transforme un camembert classique
en donut :
• width=0.45 : chaque part n’occupe que 45 % du rayon, laissant un trou central de 55 % du
rayon. C’est ce qui crée l’e et d’anneau.
• edgecolor=’white’, linewidth=2 : un liseré blanc de 2 pixels sépare chaque part, renforçant
visuellement les découpages.
textprops applique des styles par défaut à tous les textes (type, taille, couleur).

Stylisation des pourcentages

for texte_auto in textes_auto:


texte_auto.set_color(‘white’)
texte_auto.set_fontsize(12)
texte_auto.set_fontweight(‘bold’)

Cette boucle reformate les pourcentages en blanc gras, pour qu’ils restent lisibles sur les
couleurs variées des segments. Le blanc fonctionne bien sur la plupart des fonds colorés
saturés. Pour les segments trop clairs (comme le jaune Électrik), un contour noir autour du
texte aurait pu être ajouté pour encore plus de robustesse.

Le texte central du donut


axes_pie.text(0, 0.08, f"{total_pokemon}", ha=’center’, va=’center’, fontsize=32, fontweight=’bold’,
Exemples pratiques avec Matplotlib 203
color=’black’)
axes_pie.text(0, 0.10, "Pokemon", ha=’center’, va=’center’, fontsize=13, color=’grey’, style=’italic’)

C’est la signature visuelle du donut : le trou central devient un espace d’information. Deux
textes sont superposés :
• Le nombre total (1160, la somme des e ectifs) en grand et gras.
• Le mot Pokemon en plus petit, gris et italique.
Les coordonnées (0, 0.08) et (0, -0.10) placent les textes à proximité du centre (0, 0) du
diagramme, en y décalant très légèrement pour séparer les deux lignes sans qu’elles ne se
chevauchent.

Titre et sous-titre

[Link]("Répartition des Pokemon par type", fontsize=22, fontweight=’bold’, y=0.96, color=’navy’)


[Link](0.5, 0.91, "Nombre de Pokemon recensés pour chacun des 18 types",
ha=’center’, fontsize=12, style=’italic’, color=’red’)

[Link]() ajoute le titre principal sur la figure entière (et non sur un axe spécifique),
positionné à 96 % de la hauteur.
[Link]() place un sous-titre en italique rouge juste en dessous, à 91 % de la hauteur, centré
horizontalement (x=0.5). La technique du titre + sous-titre est courante dans la presse et les
rapports professionnels pour hiérarchiser l’information.

Zone dédiée à la légende

axes_legende = figure.add_axes([0.62, 0.08, 0.35, 0.82


axes_legende.set_axis_off()
legende = axes_legende.legend(
parts, labels_legende,
loc=’center left’,
frameon=True, fancybox=True, shadow=False, facecolor=’white’,
fontsize=10, framealpha=1.0, edgecolor=’black’,
title=’Type - Effectif (%’, title_fontsize=11,
handlelength=1.5, handleheight=1.2
)
legende.get_title().set_fontweight(‘bold’)

Une seconde zone est créée à droite (de 62 % à 97 % de la largeur) pour héberger uniquement
la légende.
204 Exemples pratiques avec Matplotlib

set_axis_o () masque tous les éléments de cet axe (graduations, bordures, étiquettes)
puisqu’il ne sert qu’à contenir la légende.
Le premier argument de legend() est parts (les objets graphiques récupérés lors du pie()). C’est
essentiel : Matplotlib utilise ces objets pour dessiner les carrés de couleur de la légende, en
les associant aux libellés enrichis. Sans cela, la légende ne saurait pas à quelles couleurs
faire référence.
Les paramètres handlelength=1.5, handleheight=1.2 augmentent légèrement la taille des
rectangles de couleur dans la légende pour les rendre plus visibles. Avec 18 entrées, placer la
légende hors du graphique est indispensable : une légende à l’intérieur deviendrait illisible ou
viendrait obstruer le donut.

Mention de source

[Link](0.02, 0.02, "Données illustratives - Graphique généré avec Matplotlib",


fontsize=12, style=’italic’, color=’grey’)

Mention discrète en bas à gauche, comme dans l’exemple précédent. Bonne pratique
professionnelle.

Sauvegarde et aƯichage

# affichage
[Link]("f14/graphique_09.png", facecolor=’lavender’, bbox_inches=’tight’, dpi=300
[Link]()

Sauvegarde et a ichage classiques. À noter l’absence de plt.tight_layout() car les positions


sont gérées manuellement via add_axes(), donc l’ajustement automatique n’est pas pertinent
ici.

Résultat attendu

Un diagramme en anneau coloré avec :


• 18 segments aux couleurs o icielles des types Pokémon.
• Les trois plus gros segments (Eau, Normal, Vol) détachés du centre en cascade.
• Les pourcentages en blanc gras à l’intérieur des parts.
• Les noms des types en noir gras à l’extérieur.
• Le total de Pokémon a iché en grand au centre du donut.
• Une légende détaillée à droite listant les 18 types avec e ectifs et pourcentages.
• Un titre en bleu marine et un sous-titre en rouge italique.
Exemples pratiques avec Matplotlib 205

Lecture du graphique

Les trois types dominants (Eau, Normal, Vol) représentent à eux seuls environ 30 % de l’e ectif
total. La distribution est assez étalée parmi les 18 types : contrairement à certains graphiques
où une poignée de catégories écrase les autres, ici aucune ne dépasse vraiment la barre des
12 %, ce qui témoigne d’une diversité équilibrée dans la création de la franchise.

Quand utiliser un diagramme en anneau (donut) ?

Le donut est pertinent quand :


• On veut représenter une composition proportionnelle d’un tout.
• Le nombre de catégories est modéré (idéalement 3 à 8, exceptionnellement jusqu’à 15-20
avec une légende soignée comme ici).
• Le centre libre peut accueillir une information synthétique utile (total, moyenne, valeur
clé).
• L’aspect moderne et épuré est recherché (rapports, tableaux de bord, présentations).
Limites à connaître :
• Comparer visuellement deux parts de tailles proches est plus di icile qu’avec un
diagramme en barres horizontales.
• Au-delà de 10-12 segments, la lecture devient confuse sans légende externe bien
structurée.
• Les camemberts et donuts sont critiqués en visualisation de données (data viz) : pour une
comparaison rigoureuse, un bar chart horizontal trié est souvent plus e icace. Le donut
reste cependant très populaire pour son impact visuel et sa capacité à communiquer
rapidement une idée de composition.
Dans ce cas précis, l’usage est bien justifié : 18 catégories réparties équitablement, codes
couleur reconnaissables de l’univers Pokémon, et un total central qui apporte une information
synthétique. Le résultat est plus évocateur qu’un simple graphique en barres, même s’il ne
serait pas le meilleur choix pour une analyse statistique fine.

10 - Série temporelle boursière

Dans ce paragraphe, on compose un graphique de série temporelle de niveau publication


avec :
• Des données générées par Faker (locale fr_FR) simulant un cours boursier réaliste.
• Une marche aléatoire géométrique (modèle financier standard).
• Des moyennes mobiles à 30 et 90 jours.
• Des annotations des points extrêmes.
• Une mise en forme 300 dpi prête à imprimer.
206 Exemples pratiques avec Matplotlib

import [Link] as mdates


from faker import Faker
generateur_faker = Faker(‘fr_FR’)
[Link](42)
[Link](42)

Génération des données boursières


On simule un cours boursier avec :
• Une marche aléatoire géométrique : Pt+1 = Pt * eμ+σε
• Une tendance haussière annuelle.
• Des jours ouvrés uniquement (pas de weekends).
• Des volumes échangés générés par Faker.

def generer_donnees_boursieres(date_debut=’20260101’, date_fin=’20261231’,


prix_initial=150.0, volatilite=0.015, tendance_annuelle=0.12
"""
Genere un DataFrame de donnees boursieres realistes.

Simule une marche aleatoire geometrique (modele standard en finance)


avec une tendance haussiere et des jours ouvres uniquement.
"""
# Dates des jours ouvres
tableau_dates = pd.bdate_range(start=date_debut, end=date_fin)
nombre_jours = len(tableau_dates)
# Marche aleatoire geometrique avec derive
rendement_journalier = tendance_annuelle / 252
chocs_aleatoires = [Link](rendement_journalier, volatilite, nombre_jours)
facteurs_cumules = [Link]([Link](chocs_aleatoires))
prix_cloture = prix_initial * facteurs_cumules
# Prix hauts/bas coherents (+/ 0.75% autour de la cloture)
ecarts_intraday = [Link]([Link](0, volatilite * 0.5, nombre_jours))
prix_haut = prix_cloture * 1  ecarts_intraday)
prix_bas = prix_cloture * 1  ecarts_intraday)
# Prix d’ouverture = cloture du jour precedent
prix_ouverture = [Link](prix_cloture, 1
Exemples pratiques avec Matplotlib 207
prix_ouverture[0] = prix_initial
# Volumes echanges generes avec Faker
volumes = [generateur_faker.pyint(min_value=500_000, max_value=3_000_000
for _ in range(nombre_jours)]
dataframe_resultat = [Link]({
‘date’: tableau_dates,
‘ouverture’: [Link](prix_ouverture, 2,
‘haut’: [Link](prix_haut, 2,
‘bas’: [Link](prix_bas, 2,
‘cloture’: [Link](prix_cloture, 2,
‘volume’: volumes
})
return dataframe_resultat
# visualisation
df_bourse = generer_donnees_boursieres()
print(df_bourse)

date ouverture haut bas cloture volume


0 2026-01-01 150.00 151.26 151.13 151.19 966956
1 2026-01-02 151.19 154.62 147.28 150.95 604902
2 2026-01-05 150.95 153.67 151.33 152.50 1653556
3 2026-01-06 152.50 156.39 155.80 156.10 1527150
4 2026-01-07 156.10 157.08 154.17 155.62 1436213
.. ... ... ... ... ... ...
256 2026-12-25 169.96 174.58 172.03 173.31 2137547
257 2026-12-28 173.31 171.68 171.43 171.56 1612342
258 2026-12-29 171.56 173.76 171.81 172.79 2408443
259 2026-12-30 172.79 177.08 172.70 174.89 1696421
260 2026-12-31 174.89 173.26 171.85 172.56 2274221

[261 rows x 6 columns]

print(f"Nombre de jours ouvres : {len(df_bourse)}")


print(f"Periode : {df_bourse[‘date’].min().date()} → {df_bourse[‘date’].max().date()}")
print(f"Prix min : {df_bourse[‘cloture’].min():.2f} €")
print(f"Prix max : {df_bourse[‘cloture’].max():.2f} €")

Nombre de jours ouvres : 261


Periode : 2026-01-01 -> 2026-12-31
208 Exemples pratiques avec Matplotlib

Prix min : 128.47 €


Prix max : 174.98 €

Calcul des indicateurs techniques

Moyennes mobiles à 30 et 90 jours pour lisser les tendances.

df_bourse[‘mm_30’] = df_bourse[‘cloture’].rolling(window=30.mean()
df_bourse[‘mm_90’] = df_bourse[‘cloture’].rolling(window=90.mean()
# Identification des points remarquables
indice_max = df_bourse[‘cloture’].idxmax()
indice_min = df_bourse[‘cloture’].idxmin()
prix_max = df_bourse.loc[indice_max, ‘cloture’]
prix_min = df_bourse.loc[indice_min, ‘cloture’]
date_max = df_bourse.loc[indice_max, ‘date’]
date_min = df_bourse.loc[indice_min, ‘date’]
print(f"Maximum : {prix_max:.2f} € le {date_max.strftime(‘%d/%m/%Y’)}")
print(f"Minimum : {prix_min:.2f} € le {date_min.strftime(‘%d/%m/%Y’)}")

Maximum : 174.98 € le 22/12/2026


Minimum : 128.47 € le 16/03/2026

Composition graphique

On compose un graphique financier typique de l’analyse boursière (figure 10), représentant


l’évolution du cours d’une action sur une année. Il combine une courbe de prix, deux moyennes
mobiles, une aire sous la courbe, des annotations sur les extrêmes (min et max), un formatage
spécifique des dates, et un encadré statistique récapitulatif.

import [Link] as peffects


[Link]({
‘[Link]’:’Roboto Condensed’,
‘[Link]’:’16’
})
# Palette de couleurs
couleur_cloture = ‘navy’
couleur_mm30  ‘orange’
couleur_mm90  ‘red’
Exemples pratiques avec Matplotlib 209

Figure n°10

# Creation de la figure haute resolution


figure, axe = [Link](figsize=(14, 7, dpi=300, facecolor=’lightblue’)
axe.set_facecolor(‘white’)
# Aire sous la courbe pour accentuer la lisibilite
axe.fill_between(df_bourse[‘date’], df_bourse[‘cloture’], df_bourse[‘cloture’].min() * 0.95,
color=couleur_cloture, alpha=0.08, zorder=2
# Courbe principale : prix de cloture
[Link](df_bourse[‘date’], df_bourse[‘cloture’],
color=couleur_cloture, linewidth=2.0, label=’Prix de clôture’, zorder=4
# Moyennes mobiles
[Link](df_bourse[‘date’], df_bourse[‘mm_30’],
color=couleur_mm30, linewidth=2, linestyle=’--’,
label=’Moyenne mobile 30 jours’, zorder=5
[Link](df_bourse[‘date’], df_bourse[‘mm_90’],
color=couleur_mm90, linewidth=2, linestyle=’:’,
label=’Moyenne mobile 90 jours’, zorder=5
# Annotation du maximum
[Link](date_max, prix_max, color=’lime’, s=100, zorder=6, edgecolor=’black’, linewidth=2
[Link](f’Maximum\n{prix_max:.2f} €’, xy=(date_max, prix_max),
xytext=(20, 20, textcoords=’offset points’,
210 Exemples pratiques avec Matplotlib

fontsize=12, fontweight=’bold’, color=’green’,


bbox=dict(boxstyle=’round,pad=0.4’, facecolor=’white’, edgecolor=’green’, alpha=0.9,
arrowprops=dict(arrowstyle=’→,’ color=’green’, lw=1.5
# Annotation du minimum
[Link](date_min, prix_min, color=’lime’, s=100, zorder=6, edgecolor=’black’, linewidth=2
[Link](f’Minimum\n{prix_min:.2f} €’, xy=(date_min, prix_min),
xytext=(20, 30, textcoords=’offset points’,
fontsize=12, fontweight=’bold’, color=’crimson’,
bbox=dict(boxstyle=’round,pad=0.4’, facecolor=’white’, edgecolor=’crimson’, alpha=0.9,
arrowprops=dict(arrowstyle=’→,’ color=’crimson’, lw=1.5
# Formatage de l’axe des dates
[Link].set_major_locator([Link]())
[Link].set_major_formatter([Link](‘%b %Y’))
[Link].set_minor_locator([Link](byweekday=[Link]
# Formatage de l’axe des prix (avec symbole €
[Link].set_major_formatter([Link](lambda valeur, _: f’{valeur:.0f} €’))
# Titres et labels
axe.set_title("Evolution du cours boursier - Annee 2026",
fontsize=22, fontweight=’bold’, pad=20, color=’navy’)
axe.set_xlabel("Date", fontweight=’semibold’, labelpad=10
axe.set_ylabel("Prix de clôture (€", fontweight=’semibold’, labelpad=10
# Rotation des dates
[Link](axe.get_xticklabels(), rotation=30, ha=’right’, fontsize=12
# Grille a deux niveaux
[Link](True, which=’major’, linestyle=’--’, alpha=0.4, zorder=0
[Link](True, which=’minor’, linestyle=’:’, alpha=0.15, zorder=0
axe.set_axisbelow(True)
# Epuration des bordures
for position in [‘top’, ‘right’]:
[Link][position].set_visible(False)
for position in [‘left’, ‘bottom’]:
[Link][position].set(color=’red’, linewidth=3.0
# Legende stylisee
legende = [Link](loc=’upper left’, frameon=True, fancybox=True, shadow=True,
fontsize=12, framealpha=1.0, edgecolor=’black’, title=’Indicateurs’, title_fontsize=14
legende.get_title().set_fontweight(‘bold’)
# Encadre statistique
Exemples pratiques avec Matplotlib 211
variation_totale = ((df_bourse[‘cloture’].iloc[-1] - df_bourse[‘cloture’].iloc[0])
/ df_bourse[‘cloture’].iloc[0] * 100
texte_stats = (f"Ouverture : {df_bourse[‘cloture’].iloc[0]:.2f} €\n"
f"Cloture : {df_bourse[‘cloture’].iloc[-1]:.2f} €\n"
f"Variation : {variation_totale:+.2f} %\n"
f"Volatilite : {df_bourse[‘cloture’].pct_change().std() * 100.2f} %")
[Link](0.985, 0.04, texte_stats,
transform=[Link], fontsize=12, family=’monospace’,
verticalalignment=’bottom’, horizontalalignment=’right’,
bbox=dict(boxstyle=’round,pad=0.8’, facecolor=’white’, edgecolor=’blue’, alpha=0.95
# Source
[Link](0.02, 0.02, "Données simulées avec Faker (fr_FR  Graphique généré avec Matplotlib",
fontsize=12, style=’italic’, color=’grey’)
plt.tight_layout()
[Link]("f14/graphique_10.png",facecolor=’lightblue’,bbox_inches=’tight’,dpi=300
[Link]()

Particularité : le graphique financier temporel avec moyennes mobiles

C’est la grande nouveauté de ce graphique. L’analyse des séries temporelles financières


repose sur quelques conventions visuelles spécifiques. Les moyennes mobiles (moving
averages) sont des courbes lissées calculées à partir des prix de clôture. Pour une moyenne
mobile sur 30 jours, chaque point de la courbe représente la moyenne des 30 derniers prix.
Cela permet de :
• Gommer les variations court terme (bruit quotidien).
• Visualiser les tendances sous-jacentes.
• Détecter des croisements (quand la moyenne mobile courte traverse la moyenne mobile
longue, c’est souvent interprété comme un signal technique)
Ce graphique en propose deux : la moyenne mobile 30 jours (tendance à moyen terme,
réactive) et la moyenne mobile 90 jours (tendance à long terme, plus lisse).

Couleurs et création de la figure

couleur_cloture = ‘navy’
couleur_mm30  ‘orange’
couleur_mm90  ‘red’
figure, axe = [Link](figsize=(14, 7, dpi=300, facecolor=’lightblue’)
axe.set_facecolor(‘white’)
212 Exemples pratiques avec Matplotlib

Trois couleurs sont assignées à des variables pour garantir la cohérence entre les tracés et la
légende. La figure est large (14×7 pouces, ratio panoramique), caractéristique des graphiques
boursiers qui montrent une évolution dans le temps.

Aire sous la courbe

axe.fill_between(df_bourse[‘date’], df_bourse[‘cloture’], df_bourse[‘cloture’].min() * 0.95,


color=couleur_cloture, alpha=0.08, zorder=2

La méthode fill_between() est une nouveauté importante : elle remplit une zone entre deux
courbes (ou entre une courbe et une valeur constante). Ses paramètres :
• df_bourse[‘date’] : l’axe X (les dates).
• df_bourse[‘cloture’] : la courbe supérieure (les prix de clôture).
• df_bourse[‘cloture’].min() * 0.95 : la limite inférieure, fixée à 95 % du prix minimum (pour
laisser un peu d’espace sous la courbe).
• alpha=0.08 : une très forte transparence (8 % d’opacité), pour créer un e et d’ombre
subtile plutôt qu’une zone pleine.
Ce remplissage très discret donne du volume visuel à la courbe sans la surcharger. C’est une
technique de mise en valeur courante en visualisation de données financières.

Courbe principale et moyennes mobiles

[Link](df_bourse[‘date’], df_bourse[‘cloture’],
color=couleur_cloture, linewidth=2.0, label=’Prix de clôture’, zorder=4
[Link](df_bourse[‘date’], df_bourse[‘mm_30’], color=couleur_mm30, linewidth=2, linestyle=’--’,
label=’Moyenne mobile 30 jours’, zorder=5
[Link](df_bourse[‘date’], df_bourse[‘mm_90’], color=couleur_mm90, linewidth=2, linestyle=’:’,
label=’Moyenne mobile 90 jours’, zorder=5

Trois courbes sont superposées avec des styles de trait di érents pour faciliter la distinction :
• Prix de clôture : trait plein bleu marine.
• Moyenne mobile 30 : tirets orange.
• Moyenne mobile 90 : pointillés rouge.
Cette diversité de styles (plein, tirets, pointillés) est essentielle dans un graphique à plusieurs
courbes : elle permet de les distinguer même en impression noir et blanc ou pour des
daltoniens.

Annotations des extrêmes avec flèches

[Link](date_max, prix_max, color=’lime’, s=100, zorder=6, edgecolor=’black’, linewidth=2


Exemples pratiques avec Matplotlib 213
[Link](f’Maximum\n{prix_max:.2f} €’, xy=(date_max, prix_max),
xytext=(20, 20, textcoords=’offset points’,
fontsize=12, fontweight=’bold’, color=’green’,
bbox=dict(boxstyle=’round,pad=0.4’, facecolor=’white’, edgecolor=’green’, alpha=0.9,
arrowprops=dict(arrowstyle=’→,’ color=’green’, lw=1.5

Deux nouveautés importantes apparaissent ici :


• [Link]() trace un point unique (ou plusieurs) à des coordonnées précises.
Contrairement à plot() qui trace une courbe reliant les points, scatter() se contente
de placer des marqueurs isolés. Ici, un cercle vert fluo (lime) cerclé de noir est placé
exactement sur le prix maximum pour attirer l’œil.
• [Link]() est une version évoluée de text() qui permet de combiner un texte et une
flèche. Ses paramètres clés : xy=(date_max, prix_max) est le point pointé (où la flèche
arrive). xytext=(20, 20) est la position du texte relative au point, en pixels (20 à droite, 20
au-dessus). textcoords=’o set points’ indique que xytext est un décalage en pixels par
rapport à xy, pas une coordonnée absolue. arrowprops=dict(arrowstyle=’->’, ...) définit la
flèche avec son style, sa couleur et son épaisseur. bbox=dict(...) encadre le texte dans une
boîte arrondie.
Le résultat : une bulle d’information verte avec une flèche pointant précisément sur le
sommet du graphique, indiquant Maximum et la valeur. La même technique est appliquée au
minimum, avec une couleur crimson (rouge sombre). Cette technique est très e icace pour
mettre en évidence des points d’intérêt précis dans un graphique riche en données.

Formatage spécifique des dates

[Link].set_major_locator([Link]())
[Link].set_major_formatter([Link](‘%b %Y’))
[Link].set_minor_locator([Link](byweekday=[Link]

Le module mdates (dans [Link]) fournit des outils spécialisés pour gérer les dates
sur un axe. Trois réglages sont appliqués :
• MonthLocator() place les graduations principales tous les mois. C’est Matplotlib qui
choisit automatiquement les positions exactes en fonction de la plage de données.
• DateFormatter(‘%b %Y’) formate ces graduations au format abréviation mois / année : Jan
2026, Feb 2026, Mar 2026, etc. Le %b donne l’abréviation à 3 lettres du mois, %Y l’année
sur 4 chi res.
• WeekdayLocator(byweekday=[Link]) ajoute des graduations secondaires tous les
lundis. Ces graduations mineures, invisibles par défaut, apparaîtront grâce à la grille à
deux niveaux configurée plus bas.
Cette double granularité (mois en principal, semaines en mineur) est caractéristique des
214 Exemples pratiques avec Matplotlib

graphiques boursiers : elle permet de situer rapidement une date à l’échelle mensuelle, tout
en gardant un repère hebdomadaire plus fin.

Formatage de l’axe des prix avec symbole €

[Link].set_major_formatter([Link](lambda valeur, _: f’{valeur:.0f} €’))

FuncFormatter() permet d’appliquer une fonction personnalisée pour formater chaque


étiquette de l’axe. Ici, une fonction lambda (fonction anonyme) transforme chaque valeur
numérique en chaîne de type 120 €. Décomposons :
• lambda valeur, _ : la fonction reçoit deux arguments, la valeur numérique et la position
(non utilisée ici, d’où le _).
• f’{valeur:.0f} €’ : formatage de la valeur sans décimale, suivie du symbole €.
Résultat : les graduations Y a ichent 100 €, 110 €, etc, ce qui est immédiatement lisible pour
un graphique financier.

Rotation des dates

[Link](axe.get_xticklabels(), rotation=30, ha=’right’, fontsize=12

[Link]() (set properties) est une fonction utilitaire qui applique des propriétés à plusieurs
objets d’un coup. Ici, elle :
• Récupère toutes les étiquettes de l’axe X.
• Leur applique une rotation de 30°.
• Les aligne à droite (ha=’right’) pour que la fin du texte reste près de sa graduation.
• Fixe une taille de 12.
La rotation évite que les dates Jan 2026, Feb 2026, etc ne se chevauchent sur un axe étroit.

Grille à deux niveaux

[Link](True, which=’major’, linestyle=’--’, alpha=0.4, zorder=0


[Link](True, which=’minor’, linestyle=’:’, alpha=0.15, zorder=0
axe.set_axisbelow(True)

which=’major’ et which=’minor’ permettent de styliser séparément les deux niveaux de


graduations configurés plus haut. Le résultat :
• Une grille mensuelle en tirets discrets (40 % d’opacité).
• Une grille hebdomadaire en pointillés très légers (15 % d’opacité).
Cette superposition donne au graphique une trame de repères multi-échelles, caractéristique
des graphiques professionnels d’analyse financière.
Exemples pratiques avec Matplotlib 215

Bordures stylisées

for position in [‘top’, ‘right’]:


[Link][position].set_visible(False)
for position in [‘left’, ‘bottom’]:
[Link][position].set(color=’red’, linewidth=3.0

Les bordures haut et droite sont masquées (style épuré), tandis que les bordures gauche et
bas sont rouges épaisses, créant un cadre en L qui structure visuellement la zone de tracé.

Légende avec titre

legende = [Link](loc=’upper left’, frameon=True, fancybox=True, shadow=True,


fontsize=12, framealpha=1.0, edgecolor=’black’,
title=’Indicateurs’, title_fontsize=14
legende.get_title().set_fontweight(‘bold’)

Légende soignée en haut à gauche, avec coins arrondis, ombre portée, et surtout un titre
Indicateurs mis en gras via get_title().set_fontweight(‘bold’). Les trois séries (prix, MM 30, MM
90) y apparaissent avec leurs couleurs et styles respectifs.

Encadré statistique avec calculs dynamiques

variation_totale = ((df_bourse[‘cloture’].iloc[-1] - df_bourse[‘cloture’].iloc[0])


/ df_bourse[‘cloture’].iloc[0] * 100
texte_stats = (f"Ouverture : {df_bourse[‘cloture’].iloc[0]:.2f} €\n"
f"Cloture : {df_bourse[‘cloture’].iloc[-1]:.2f} €\n"
f"Variation : {variation_totale:+.2f} %\n"
f"Volatilite : {df_bourse[‘cloture’].pct_change().std() * 100.2f} %")

Quatre statistiques sont calculées à la volée :


• iloc[0] et iloc[-1] : accès par position au premier et au dernier élément de la série. Le -1 est
la convention Python pour désigner le dernier élément.
• La variation totale : calcule le pourcentage de variation entre le début et la fin de la
période. Le format +.2f inclut un signe explicite (+ ou –) devant la valeur, ce qui est capital
en finance pour distinguer immédiatement une hausse d’une baisse.
• La volatilité : pct_change() calcule les variations journalières en pourcentage, et std() en
prend l’écart-type. Multiplié par 100, on obtient une mesure standardisée de la dispersion
des rendements quotidiens, indicateur clé de la nervosité d’une action.
216 Exemples pratiques avec Matplotlib

• L’alignement monospace : les chaînes utilisent des espaces manuels après Cloture pour
aligner verticalement les deux-points avec Ouverture. C’est ce qui justifie le choix de la
police monospace ci-dessous.

[Link](0.985, 0.04, texte_stats, transform=[Link],


fontsize=12, family=’monospace’,
verticalalignment=’bottom’, horizontalalignment=’right’,
bbox=dict(boxstyle=’round,pad=0.8’, facecolor=’white’, edgecolor=’blue’, alpha=0.95

L’encadré est placé en bas à droite (coordonnées relatives 0.985, 0.04), encadré de bleu, en
police monospace pour garantir l’alignement des chi res en colonnes.

Mention de source et sauvegarde

[Link](0.02, 0.02,
"Données simulées avec Faker (fr_FR  Graphique généré avec Matplotlib",
fontsize=12, style=’italic’, color=’grey’)
plt.tight_layout()
[Link]("f14/graphique_10.png", facecolor=’lightblue’, bbox_inches=’tight’, dpi=300
[Link]()

Mention de source (précisant que les données proviennent de la bibliothèque Faker, un


générateur de données factices), ajustement automatique, sauvegarde et a ichage.

Résultat attendu

Un graphique financier professionnel avec :


• Une courbe bleu marine des prix de clôture quotidiens, avec une ombre bleue sous la
courbe.
• Une courbe orange en tirets de la moyenne mobile 30 jours (plus lisse que le cours, suit
les tendances courtes).
• Une courbe rouge en pointillés de la moyenne mobile 90 jours (encore plus lisse, tendance
de fond).
• Deux annotations mettant en évidence le maximum (en vert) et le minimum (en rouge)
atteints dans l’année, avec flèches précises.
• Un axe X temporel avec les mois en repères principaux et les lundis en repères secondaires
• Un axe Y avec les prix exprimés en euros.
• Une légende Indicateurs en haut à gauche.
• Un encadré statistique en bas à droite récapitulant ouverture, clôture, variation annuelle
et volatilité.
Exemples pratiques avec Matplotlib 217

Quand utiliser ce type de graphique ?

Ce format est quasi-standard dans plusieurs contextes :


• Analyse boursière et financière : suivi d’actions, d’indices, de taux de change.
• Suivi d’indicateurs économiques au fil du temps : prix de matières premières, indices de
confiance, etc.
• Rapports de performance : toute série temporelle où la tendance est aussi importante
que les valeurs ponctuelles.
Les moyennes mobiles sont particulièrement précieuses quand :
• Les données brutes présentent beaucoup de bruit qui masque la tendance.
• On veut comparer plusieurs horizons temporels (court vs moyen vs long terme).
• On recherche des signaux techniques (croisements, divergences).

Les concepts clés à retenir

Ce graphique condense plusieurs techniques utiles au-delà du contexte financier :


• Superposer plusieurs séries avec des styles de trait distincts (plein, tirets, pointillés)
plutôt que de compter uniquement sur la couleur, pour une meilleure accessibilité.
• Annoter les points remarquables avec annotate() et des flèches explicites, technique
polyvalente applicable à toute donnée comportant des valeurs extrêmes, des événements
marquants ou des seuils critiques.
• Formater les axes avec FuncFormatter() (pour les unités) et les locators/formatters
de mdates (pour les dates), transformant un graphique générique en un graphique
contextualisé et immédiatement lisible par son public cible.
• Intégrer un encadré synthétique avec des calculs à la volée, qui donne au lecteur les
indicateurs clés sans qu’il ait à les calculer lui-même. C’est l’essence d’un bon graphique
professionnel : raconter une histoire complète en un seul coup d’œil.

11 - Positionnement avec les tableaux

Dans ce paragraphe, on ne produit pas un graphique au sens classique, mais un tableau


stylisé (figure 11) généré avec Matplotlib. Il prépare les 10 dernières lignes d’un DataFrame
boursier, les met en forme, puis les a iche sous forme d’un tableau avec en-têtes colorés,
lignes alternées en zébrures, et colonne de clôture mise en évidence.

[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’ })


# SELECTION  les 10 dernieres lignes du DataFrame
nombre_lignes_affichees = 10
donnees_extraites = df_bourse.tail(nombre_lignes_affichees).drop(columns=[‘mm_30’, ‘mm_90’]).copy()
218 Exemples pratiques avec Matplotlib

Figure n°11

# Formatage des valeurs (dates en JJ/MM/AAAA, prix avec €, volume avec espaces)
donnees_extraites[‘date’] = donnees_extraites[‘date’].[Link](‘%d/%m/%Y’)
donnees_extraites[‘ouverture’] = donnees_extraites[‘ouverture’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘haut’] = donnees_extraites[‘haut’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘bas’] = donnees_extraites[‘bas’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘cloture’] = donnees_extraites[‘cloture’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘volume’] = donnees_extraites[‘volume’].map(lambda valeur: f’{valeur:,}’.replace(‘,’, ‘ ‘))
print("⇒ donnees_extraites =\n",donnees_extraites)
entetes_colonnes = [‘Date’, ‘Ouverture’, ‘Plus haut’, ‘Plus bas’, ‘Cloture’, ‘Volume’]
valeurs_tableau = donnees_extraites.[Link]()
print("⇒ valeurs_tableau =\n",valeurs_tableau)
# CREATION DE LA FIGURE 300 DPI
figure, axe = [Link](figsize=(12, 5, dpi=300, facecolor=’oldlace’)
axe.set_axis_off()
# Palette de couleurs
couleur_entete = ‘navy’
couleur_ligne_paire = ‘whitesmoke’
couleur_ligne_impaire = ‘lightgrey’
# Creation du tableau
tableau = [Link](
cellText=valeurs_tableau,
colLabels=entetes_colonnes,
Exemples pratiques avec Matplotlib 219
loc=’center’,
cellLoc=’center’,
colLoc=’center’
)
# Dimensionnement manuel
tableau.auto_set_font_size(False)
tableau.set_fontsize(11)
[Link](1, 2.2
# Stylisation des en-tetes (ligne 0
for colonne_index in range(len(entetes_colonnes)):
cellule_entete = tableau[0, colonne_index]
cellule_entete.set_facecolor(couleur_entete)
cellule_entete.set_text_props(color=’white’, fontweight=’bold’, fontsize=14
cellule_entete.set_edgecolor(‘red’)
cellule_entete.set_linewidth(2)
cellule_entete.set_height(0.12)
# Stylisation des lignes de donnees en zebra
for ligne_index in range(1, len(valeurs_tableau) + 1):
for colonne_index in range(len(entetes_colonnes)):
cellule = tableau[ligne_index, colonne_index]
if ligne_index % 2  0
cellule.set_facecolor(couleur_ligne_paire)
else:
cellule.set_facecolor(couleur_ligne_impaire)
cellule.set_edgecolor(‘darkgrey’)
cellule.set_linewidth(0.8)
cellule.set_text_props(color=’black’, fontfamily=’monospace’)
# Mise en evidence de la colonne Cloture (valeur cle)
indice_colonne_cloture = entetes_colonnes.index(‘Cloture’)
for ligne_index in range(1, len(valeurs_tableau) + 1):
cellule_cloture = tableau[ligne_index, indice_colonne_cloture]
cellule_cloture.set_text_props(color=’blue’, fontweight=’bold’, fontfamily=’monospace’)
# Titre
[Link]("Cours boursier (les 10 derniers jours cotés)",
fontsize=22, fontweight=’bold’, y=0.95, color=’navy’)
# Sous-titre
[Link](0.5, 0.86,
220 Exemples pratiques avec Matplotlib

f"Extrait du {donnees_extraites[‘date’].iloc[0]} au {donnees_extraites[‘date’].iloc[-1]}",


ha=’center’, fontsize=10, style=’italic’, color=’red’)
# Source
[Link](0.02, 0.0, "Données simulées avec Faker (fr_FR  Tableau généré avec Matplotlib",
fontsize=12, style=’italic’, color=’darkgrey’)
# affichage
plt.tight_layout()
[Link]("f14/graphique_11.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

=> donnees_extraites =
date ouverture haut bas cloture volume
251 18/12/2026 164.38 € 167.03 € 166.44 € 166.73 € 2 182 084
252 21/12/2026 166.73 € 173.38 € 171.04 € 172.21 € 745 934
253 22/12/2026 172.21 € 175.74 € 174.22 € 174.98 € 1 190 538
254 23/12/2026 174.98 € 172.09 € 170.15 € 171.12 € 2 089 528
255 24/12/2026 171.12 € 170.60 € 169.32 € 169.96 € 509 040
256 25/12/2026 169.96 € 174.58 € 172.03 € 173.31 € 2 137 547
257 28/12/2026 173.31 € 171.68 € 171.43 € 171.56 € 1 612 342
258 29/12/2026 171.56 € 173.76 € 171.81 € 172.79 € 2 408 443
259 30/12/2026 172.79 € 177.08 € 172.70 € 174.89 € 1 696 421
260 31/12/2026 174.89 € 173.26 € 171.85 € 172.56 € 2 274 221

=> valeurs_tableau =
[[‘18/12/2026’, ‘164.38 €’, ‘167.03 €’, ‘166.44 €’, ‘166.73 €’, ‘2 182 084’],
[‘21/12/2026’, ‘166.73 €’, ‘173.38 €’, ‘171.04 €’, ‘172.21 €’, ‘745 934’],
[‘22/12/2026’, ‘172.21 €’, ‘175.74 €’, ‘174.22 €’, ‘174.98 €’, ‘1 190 538’],
[‘23/12/2026’, ‘174.98 €’, ‘172.09 €’, ‘170.15 €’, ‘171.12 €’, ‘2 089 528’],
[‘24/12/2026’, ‘171.12 €’, ‘170.60 €’, ‘169.32 €’, ‘169.96 €’, ‘509 040’],
[‘25/12/2026’, ‘169.96 €’, ‘174.58 €’, ‘172.03 €’, ‘173.31 €’, ‘2 137 547’],
[‘28/12/2026’, ‘173.31 €’, ‘171.68 €’, ‘171.43 €’, ‘171.56 €’, ‘1 612 342’],
[‘29/12/2026’, ‘171.56 €’, ‘173.76 €’, ‘171.81 €’, ‘172.79 €’, ‘2 408 443’],
[‘30/12/2026’, ‘172.79 €’, ‘177.08 €’, ‘172.70 €’, ‘174.89 €’, ‘1 696 421’],
[‘31/12/2026’, ‘174.89 €’, ‘173.26 €’, ‘171.85 €’, ‘172.56 €’, ‘2 274 221’]]

Particularité : le tableau comme un graphique Matplotlib

C’est la grande nouveauté de ce code. Matplotlib est avant tout une bibliothèque de tracés
graphiques, mais elle propose aussi une fonction table() permettant de dessiner un tableau
dans une figure. Cette approche présente plusieurs avantages :
• Produire un tableau image haute résolution (300 dpi) directement exploitable dans un
rapport, une présentation ou une publication.
Exemples pratiques avec Matplotlib 221
• Appliquer une mise en forme visuelle riche (couleurs, polices, bordures) que ne
permettent pas toujours les outils bureautiques classiques.
• Combiner tableaux et graphiques dans une même figure, pour des tableaux de bord
cohérents
À noter que pour une manipulation interactive (tri, filtrage), un vrai DataFrame reste préférable.
Mais pour un rendu visuel figé, cette méthode est élégante.

Sélection et préparation des données

nombre_lignes_affichees = 10
donnees_extraites = df_bourse.tail(nombre_lignes_affichees).drop(columns=[‘mm_30’, ‘mm_90’]).copy()

Trois opérations enchaînées via la syntaxe chainée (method chaining) :


• tail(10) : extrait les 10 dernières lignes du DataFrame. C’est le miroir de head() qui renvoie
les premières lignes.
• drop(columns=[‘mm_30’, ‘mm_90’]) : supprime les colonnes des moyennes mobiles, qui
n’ont pas besoin d’apparaître dans ce tableau synthétique.
• copy() est important : sans cette copie explicite, modifier donnees_extraites pourrait
a ecter le DataFrame d’origine df_bourse (avec un avertissement Pandas de type
SettingWithCopyWarning). Le copy() garantit qu’on travaille sur une copie indépendante.

Formatage des valeurs pour aƯichage

donnees_extraites[‘date’] = donnees_extraites[‘date’].[Link](‘%d/%m/%Y’)
donnees_extraites[‘ouverture’] = donnees_extraites[‘ouverture’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘haut’] = donnees_extraites[‘haut’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘bas’] = donnees_extraites[‘bas’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘cloture’] = donnees_extraites[‘cloture’].map(lambda valeur: f’{valeur:.2f} €’)
donnees_extraites[‘volume’] = donnees_extraites[‘volume’].map(lambda valeur: f’{valeur:,}’.replace(‘,’, ‘ ‘))

Cette étape convertit les valeurs numériques en chaînes de caractères formatées. Plusieurs
techniques intéressantes :
• [Link](‘%d/%m/%Y’) : l’accesseur dt donne accès aux méthodes de manipulation de
dates Pandas. strftime() (string format time) convertit chaque date en chaîne au format
jour/mois/année.
• map(lambda valeur: f’{valeur:.2f} €’) : la méthode map() applique une fonction à chaque
valeur d’une colonne. La fonction lambda transforme le nombre en chaîne à 2 décimales
suivi du symbole €. Exemple : 123.456 devient ’123.46 €’.
Le format f’{valeur:,}’.replace(‘,’, ‘ ‘) mérite une attention particulière. Le format :, insère une
virgule comme séparateur de milliers (convention anglo-saxonne), donc 1234567 devient
222 Exemples pratiques avec Matplotlib

’1,234,567’. Le replace(‘,’, ‘ ‘) remplace ensuite ces virgules par des espaces insécables,
respectant la convention typographique française (1 234 567). C’est une astuce classique en
Python pour obtenir le format français des nombres.

Préparation pour le tableau Matplotlib

entetes_colonnes = [‘Date’, ‘Ouverture’, ‘Plus haut’, ‘Plus bas’, ‘Cloture’, ‘Volume’]


valeurs_tableau = donnees_extraites.[Link]()

Les en-têtes sont définis manuellement en français (avec des libellés plus lisibles que les
noms techniques du DataFrame). donnees_extraites.[Link]() convertit le DataFrame en
liste de listes Python. Chaque sous-liste représente une ligne. C’est le format attendu par la
fonction table() de Matplotlib.

Création de la figure sans axes visibles

figure, axe = [Link](figsize=(12, 5, dpi=300, facecolor=’oldlace’)


axe.set_axis_off()

axe.set_axis_o () est une instruction importante : elle masque complètement l’axe (bordures,
graduations, étiquettes). Le tableau deviendra le seul contenu visible de la zone. Sans cela,
des axes vides encadreraient le tableau, visuellement disgracieux.

Définition des couleurs

couleur_entete = ‘navy’
couleur_ligne_paire = ‘whitesmoke’
couleur_ligne_impaire = ‘lightgrey’

Trois couleurs sont définies à l’avance pour garantir la cohérence et faciliter les modifications
ultérieures. C’est une bonne pratique : si on veut changer la charte graphique, il su it de
modifier ces trois variables au lieu de chercher les couleurs dans tout le code.

Création du tableau

tableau = [Link](
cellText=valeurs_tableau,
colLabels=entetes_colonnes,
loc=’center’,
cellLoc=’center’,
Exemples pratiques avec Matplotlib 223
colLoc=’center’
)

La méthode [Link]() crée le tableau. Ses paramètres :


• cellText : la liste de listes contenant les valeurs des cellules.
• colLabels : la liste des en-têtes de colonnes, placés automatiquement en ligne 0.
• loc=’center’ : le tableau est centré dans la zone de tracé.
• cellLoc=’center’ : le contenu des cellules est centré horizontalement et verticalement.
• colLoc=’center’ : les libellés de colonnes sont aussi centrés.

Dimensionnement manuel

tableau.auto_set_font_size(False)
tableau.set_fontsize(11)
[Link](1, 2.2

auto_set_font_size(False) désactive le dimensionnement automatique de la police. Sans


cette instruction, Matplotlib ajusterait la taille selon l’espace disponible, ignorant la taille
demandée ensuite.
set_fontsize(11) fixe explicitement la taille à 11 points.
scale(1, 2.2) est un paramètre important : il multiplie la largeur des cellules par 1 (inchangée)
et la hauteur par 2.2. Par défaut, les cellules de tableau Matplotlib sont très plates et donnent
une impression d’étou ement. Augmenter la hauteur de 2.2× rend le tableau beaucoup plus
aéré et lisible.

Stylisation des en-têtes

for colonne_index in range(len(entetes_colonnes)):


cellule_entete = tableau[0, colonne_index]
cellule_entete.set_facecolor(couleur_entete)
cellule_entete.set_text_props(color=’white’, fontweight=’bold’, fontsize=14
cellule_entete.set_edgecolor(‘red’)
cellule_entete.set_linewidth(2)
cellule_entete.set_height(0.12)

Cette boucle parcourt les cellules de la ligne 0 (les en-têtes) et leur applique un style distinct :
• tableau[ligne, colonne] permet d’accéder individuellement à une cellule du tableau,
comme avec une matrice. C’est la clé pour personnaliser finement chaque cellule.
• set_facecolor() : fond bleu marine pour les en-têtes.
• set_text_props() : propriétés du texte regroupées dans un seul appel, blanc, gras, taille 14
224 Exemples pratiques avec Matplotlib

pour bien dissocier les en-têtes des données.


• set_edgecolor(‘red’) et set_linewidth(2) : bordures rouges épaisses, qui encadrent vivement
la ligne d’en-tête.
• set_height(0.12) : hauteur personnalisée, pour que la ligne d’en-tête soit plus haute que
les lignes de données.

Lignes alternées en zébrures

for ligne_index in range(1, len(valeurs_tableau) + 1):


for colonne_index in range(len(entetes_colonnes)):
cellule = tableau[ligne_index, colonne_index]
if ligne_index % 2  0
cellule.set_facecolor(couleur_ligne_paire)
else:
cellule.set_facecolor(couleur_ligne_impaire)
cellule.set_edgecolor(‘darkgrey’)
cellule.set_linewidth(0.8)
cellule.set_text_props(color=’black’, fontfamily=’monospace’)

C’est l’e et zébrure (zebra striping), une technique classique de lisibilité. Le principe : alterner
deux couleurs de fond entre les lignes paires et impaires pour guider l’œil horizontalement et
éviter les erreurs de lecture sur les grandes lignes.
ligne_index % 2 == 0 : le modulo 2 teste si l’indice est pair. La double boucle parcourt toutes les
cellules de toutes les lignes de données (sautant la ligne 0 des en-têtes).
fontfamily=’monospace’ : les valeurs sont a ichées en police à chasse fixe, ce qui aligne
verticalement les chi res (points décimaux, symboles €, espaces de séparation des milliers).
C’est indispensable pour un tableau numérique lisible. Sans monospace, les chi res seraient
décalés selon leur largeur (le 1 étant plus étroit que le 8 par exemple), rendant la comparaison
colonne par colonne plus di icile.

Mise en évidence de la colonne Clôture

indice_colonne_cloture = entetes_colonnes.index(‘Cloture’)
for ligne_index in range(1, len(valeurs_tableau) + 1):
cellule_cloture = tableau[ligne_index, indice_colonne_cloture]
cellule_cloture.set_text_props(color=’blue’, fontweight=’bold’, fontfamily=’monospace’)

entetes_colonnes.index(‘Cloture’) récupère l’indice (la position) de la colonne Cloture dans la


liste des en-têtes. C’est plus robuste que coder en dur un numéro : si l’ordre des colonnes
Exemples pratiques avec Matplotlib 225
change, ce code continuera à fonctionner. La boucle applique ensuite un style bleu gras aux
valeurs de cette colonne, car le prix de clôture est la valeur de référence en analyse boursière
(celle qu’on utilise pour construire les courbes, calculer les moyennes mobiles, etc). Cette
mise en évidence guide le lecteur vers l’information la plus importante du tableau.

Titre et sous-titre

[Link]("Cours boursier (les 10 derniers jours cotés)",


fontsize=22, fontweight=’bold’, y=0.95, color=’navy’)
[Link](0.5, 0.86,
f"Extrait du {donnees_extraites[‘date’].iloc[0]} au {donnees_extraites[‘date’].iloc[-1]}",
ha=’center’, fontsize=10, style=’italic’, color=’red’)

Le titre principal est en bleu marine, cohérent avec la couleur des en-têtes. Le sous-titre est
dynamique : il utilise les premières et dernières dates du tableau pour former un texte du
type Extrait du 01/12/2026 au 10/12/2026. Cela contextualise automatiquement l’extrait sans
nécessiter de modification manuelle à chaque exécution.

Source, sauvegarde et aƯichage

[Link](0.02, 0.0,
"Données simulées avec Faker (fr_FR  Tableau généré avec Matplotlib",
fontsize=12, style=’italic’, color=’darkgrey’)
plt.tight_layout()
[Link]("f14/graphique_11.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300
[Link]()

Mention de source discrète, puis sauvegarde et a ichage.

Résultat attendu

Un tableau visuellement soigné avec :


• Un en-tête bleu marine avec texte blanc gras encadré de rouge.
• 10 lignes de données alternant whitesmoke et lightgrey (zébrures).
• La colonne Clôture mise en évidence en bleu gras.
• Toutes les valeurs en police monospace pour un alignement numérique parfait.
• Un titre bleu marine et un sous-titre rouge italique indiquant la période couverte.
• Une mention de source discrète en bas.
Le tableau a iche six colonnes : Date, Ouverture, Plus haut, Plus bas, Clôture, Volume, les
données brutes complémentaires à la courbe boursière du graphique précédent.
226 Exemples pratiques avec Matplotlib

Quand utiliser un tableau Matplotlib ?


Cette technique est particulièrement adaptée pour :
• Compléter un graphique dans une même figure (tableau de bord), par exemple pour
a icher les données brutes sous-jacentes à une courbe.
• Produire des tableaux imprimables haute résolution pour rapports ou publications.
• Créer des extraits synthétiques de données volumineuses (les 10 dernières lignes, les 5
plus grosses valeurs, etc).
• Garantir une mise en forme cohérente avec d’autres graphiques Matplotlib (même police,
mêmes couleurs).
Limites à connaître :
• Ce n’est pas interactif : pas de tri, filtrage ou recherche comme dans un vrai DataFrame
a iché dans un notebook.
• La gestion automatique des dimensions est limitée : il faut souvent ajuster manuellement
via scale() et set_height().
• Pour des tableaux volumineux (plusieurs dizaines de lignes ou colonnes), des
bibliothèques spécialisées comme Pandas Styler (rendu HTML), great_tables ou plotly
o rent plus de possibilités.

Les concepts clés à retenir


Ce code illustre plusieurs techniques transposables :
• Formater des données Pandas en chaînes présentables via map(lambda ...), [Link](...),
et les format spécifiers Python (:.2f, :,, etc). Le détour par replace(‘,’, ‘ ‘) pour obtenir le
format français est un idiome pratique.
• Accéder aux cellules par coordonnées avec tableau[ligne, colonne] pour personnaliser
finement chaque zone : en-têtes, lignes paires/impaires, colonne mise en évidence. C’est
ce qui distingue un tableau brut d’un tableau professionnel.
• Utiliser la police monospace pour les tableaux numériques : c’est un détail d’apparence
qui change radicalement la lisibilité des colonnes de chi res.
• Anticiper la maintenance via les variables de couleurs et entetes_colonnes.index() :
un code bien structuré résiste mieux aux évolutions futures (changement de charte
graphique, réordonnancement des colonnes, ajout de lignes, etc).

12 - Nuages de points

Dans ce paragraphe, on compose un nuage de points (scatter plot) à quatre dimensions


analysant la pandémie de coronavirus dans 26 pays (figure 12). Il combine la position
horizontale (mortalité), la position verticale (tests quotidiens), la taille des points (cas
confirmés totaux) et leur couleur (intensité de la mortalité), soit quatre variables représentées
simultanément sur un même graphique.
Exemples pratiques avec Matplotlib 227

Figure n°12

[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’})


# données
tableau_pays = [Link]([‘Australie’, ‘Bresil’, ‘Canada’, ‘Chili’, ‘France’, ‘Allemagne’, ‘Grece’,
‘Islande’, ‘Inde’, ‘Iran’, ‘Italie’, ‘Mexique’, ‘Nouvelle-Zelande’, ‘Nigeria’,
‘Norvege’, ‘Pakistan’, ‘Perou’, ‘Russie’, ‘Arabie Saoudite’, ‘Singapour’,
‘Afrique du Sud’, ‘Espagne’, ‘Suede’, ‘Turquie’, ‘Royaume-Uni’, ‘Etats-Unis’])
tableau_mortalite = [Link]([1.8, 53, 24.5, 56.5, 45.4, 11.2, 2.2, 2.8, 4, 24.6, 58.6, 46.3, .5, .5,
4.9, 2.9, 83.3, 11, 10.4, .5, 21.5, 61.6, 56.9, 7.3, 62.4, 52.9
tableau_tests = [Link]([110, 7197, 600, 1862, 1636, 1103, 35, 10, 295, 1658, 1226, 2490, 8, 243,
48, 1395, 1101, 4447, 1443, 280, 2830, 1602, 447, 1205, 1546, 24988
tableau_cas_confirmes = [Link]([
24236, 3456652, 125408, 390037, 256534, 229706, 7684,
2035, 2836925, 350279, 255278, 537031, 1654, 50488,
10162, 290445, 549321, 935066, 302686, 56031,
596060, 370867, 85411, 253108, 323008, 5529824
# Normalisation de la taille des points sur [50, 2000
228 Exemples pratiques avec Matplotlib

taille_min, taille_max = 50, 2000


tailles_normalisees = (tableau_cas_confirmes - tableau_cas_confirmes.min()) / \
(tableau_cas_confirmes.max() - tableau_cas_confirmes.min())
tailles_points = tailles_normalisees * (taille_max - taille_min) + taille_min
# graphique Figure 300 dpi
figure, axe = [Link](figsize=(14, 9, dpi=300, facecolor=’oldlace’)
axe.set_facecolor(‘whitesmoke’)
# Nuage de points : couleur = mortalite, taille = cas confirmes
nuage_points = [Link](
tableau_mortalite, tableau_tests,
s=tailles_points,
c=tableau_mortalite,
cmap=’YlOrRd’,
alpha=0.75,
edgecolors=’black’,
linewidths=1.2,
zorder=4
)
# Barre de couleur
barre_couleurs = [Link](nuage_points, ax=axe, pad=0.02, shrink=0.85
barre_couleurs.set_label(‘Taux de mortalité pour 100k habitants’,
fontsize=12, fontweight=’semibold’, labelpad=10
barre_couleurs.ax.tick_params(labelsize=12
# Annotation des pays remarquables (top 5  extremes)
indices_top_cas = [Link](tableau_cas_confirmes)[-5:]
indice_max_mortalite = [Link](tableau_mortalite)
indice_max_tests = [Link](tableau_tests)
indices_a_annoter = set(indices_top_cas.tolist() + [indice_max_mortalite, indice_max_tests])
for indice in indices_a_annoter:
[Link](
tableau_pays[indice],
xy=(tableau_mortalite[indice], tableau_tests[indice]),
xytext=(10, 10, textcoords=’offset points’,
fontsize=12, fontweight=’bold’, color=’navy’,
bbox=dict(boxstyle=’round,pad=0.5’, facecolor=’white’, edgecolor=’black’, alpha=0.85,
zorder=6 
# Ligne de reference : mediane mortalite
Exemples pratiques avec Matplotlib 229
mediane_mortalite = [Link](tableau_mortalite)
mediane_tests = [Link](tableau_tests)
[Link](mediane_mortalite, color=’orange’, linestyle=’--’, linewidth=2.0, alpha=0.6, zorder=2
[Link](mediane_tests, color=’orange’, linestyle=’--’, linewidth=2.0, alpha=0.6, zorder=2
[Link](mediane_mortalite + 1, axe.get_ylim()[1 * 0.98,
f’ Médiane mortalité : {mediane_mortalite:.1f}’,
rotation=90, va=’top’, ha=’left’, fontsize=12, color=’black’, style=’italic’)
# Echelle log pour l’axe Y (forte dispersion entre 8 et 24988
axe.set_yscale(‘log’)
# Titre et labels
axe.set_title("Pandémie de Coronavirus : mortalité vs cas confirmés quotidiens",
fontsize=22, fontweight=’bold’, pad=25, color=’navy’)
axe.set_xlabel("Taux de mortalité pour 100 000 habitants",
fontweight=’semibold’, labelpad=10, color=’blue’)
axe.set_ylabel("Cas confirmés quotidiens (echelle log)",
fontweight=’semibold’, labelpad=10, color=’blue’)
# Grille
[Link](True, which=’major’, linestyle=’--’, alpha=0.4, zorder=0, color=’grey’)
[Link](True, which=’minor’, linestyle=’:’, alpha=0.15, zorder=0, color=’grey’)
axe.set_axisbelow(True)
# Bordures epurees
for position in [‘top’, ‘right’]:
[Link][position].set_visible(False)
for position in [‘left’, ‘bottom’]:
[Link][position].set(color=’blue’, linewidth=2.0
# Legende personnalisee pour la taille des points
valeurs_reference = [100_000, 1_000_000, 5_000_000
legendes_taille = []
for valeur in valeurs_reference:
taille_normalisee = (valeur - tableau_cas_confirmes.min()) / \
(tableau_cas_confirmes.max() - tableau_cas_confirmes.min())
taille_affichee = taille_normalisee * (taille_max - taille_min) + taille_min
cercle = [Link]([], [], s=taille_affichee, color=’lightgray’, edgecolors=’black’, linewidths=1.2,
alpha=0.75, label=f’ {valeur:,} cas’.replace(‘,’, ‘ ‘))
legendes_taille.append(cercle)
legende = [Link](handles=legendes_taille, loc=’center’,
title=’Taille du marqueur (total des cas confirmés)’,
230 Exemples pratiques avec Matplotlib

title_fontsize=12, fontsize=12, ncols=3,


frameon=True, fancybox=True, shadow=True,
framealpha=1.0, edgecolor=’black’, facecolor=’oldlace’,
labelspacing=2.5, borderpad=2.5, bbox_to_anchor=(0.5,0.0,0.0,0.6
legende.get_title().set_fontweight(‘bold’)
# Encadre statistique
texte_stats = (f"Pays analyses : {len(tableau_pays)}\n"
f"Total cas : {tableau_cas_confirmes.sum():,}".replace(‘,’, ‘ ‘) + "\n"
f"Mortalite moyenne : {tableau_mortalite.mean():.1f}\n"
f"Tests quotidiens moyens : {tableau_tests.mean():.0f}")
[Link](0.4, 0.2, texte_stats,
transform=[Link],
fontsize=12, family=’monospace’,
verticalalignment=’top’, horizontalalignment=’left’,
bbox=dict(boxstyle=’round,pad=0.8’, facecolor=’white’, edgecolor=’black’, alpha=0.95
# source
[Link](0.02, 0.15, "Données illustratives\nGraphique généré avec Matplotlib",
fontsize=12, style=’italic’, color=’grey’)
# affichage
plt.tight_layout()
[Link]("f14/graphique_12.png",facecolor=’oldlace’,bbox_inches=’tight’,dpi=300
[Link]()

Particularité : le nuage de points multidimensionnel

C’est la grande nouveauté de ce graphique. Un scatter plot classique représente deux variables
(X et Y), mais Matplotlib permet d’y ajouter deux dimensions supplémentaires via :
• La taille des marqueurs (paramètre s).
• La couleur des marqueurs (paramètre c couplé à une palette cmap).
Ce type de visualisation, parfois appelé bulle (bubble chart), est précieux en analyse exploratoire
quand on cherche à détecter des relations entre plusieurs variables simultanément. Il est
particulièrement adapté aux comparaisons entre entités (pays, entreprises, produits) où
chaque point représente une unité distincte.

Préparation des données

tableau_pays = [Link]([‘Australie’, ‘Bresil’, ...])


Exemples pratiques avec Matplotlib 231
tableau_mortalite = [Link]([1.8, 53, 24.5, ...])
tableau_tests = [Link]([110, 7197, 600, ...])
tableau_cas_confirmes = [Link]([24236, 3456652, 125408, ...])

Quatre tableaux parallèles contiennent les données : le nom du pays, son taux de mortalité,
son nombre de tests quotidiens et son total de cas confirmés. Chaque indice (0, 1, 2…)
correspond à un même pays dans les quatre tableaux. Cette structure est essentielle pour
que les coordonnées, tailles et couleurs restent cohérentes.

Normalisation des tailles

taille_min, taille_max = 50, 2000


tailles_normalisees = (tableau_cas_confirmes - tableau_cas_confirmes.min()) / \
(tableau_cas_confirmes.max() - tableau_cas_confirmes.min())
tailles_points = tailles_normalisees * (taille_max - taille_min) + taille_min

C’est une étape technique importante. Les cas confirmés varient de quelques milliers à
plusieurs millions : on ne peut pas utiliser ces chi res bruts comme tailles de marqueurs, car
un point de 5 529 824 pixels serait absurde. La normalisation min-max (deux premières lignes
du calcul) ramène toutes les valeurs dans l’intervalle [0, 1] :
• La valeur minimale devient 0.
• La valeur maximale devient 1.
• Les autres valeurs sont réparties proportionnellement entre ces deux bornes.
La dénormalisation (troisième ligne) transforme ensuite ces valeurs normalisées vers
l’intervalle visuellement exploitable [50, 2000]. Ainsi, le pays avec le moins de cas a ichera
un marqueur de 50 unités, celui avec le plus de cas un marqueur de 2000 unités, et les autres
seront dimensionnés proportionnellement.
À retenir : cette technique de normalisation min-max est un réflexe utile dans toutes les
visualisations où une variable doit être mappée sur une plage visuelle (taille, couleur, opacité,
épaisseur, etc).

Création de la figure

figure, axe = [Link](figsize=(14, 9, dpi=300, facecolor=’oldlace’)


axe.set_facecolor(‘whitesmoke’)

Figure large (14×9 pouces) pour accueillir de nombreux points et annotations sans
encombrement.
232 Exemples pratiques avec Matplotlib

Le nuage de points multi-dimensionnel

nuage_points = [Link](
tableau_mortalite, tableau_tests,
s=tailles_points,
c=tableau_mortalite,
cmap=’YlOrRd’,
alpha=0.75,
edgecolors=’black’,
linewidths=1.2,
zorder=4
)

C’est le cœur du graphique. Plusieurs paramètres définissent simultanément les quatre


dimensions :
• Les coordonnées : tableau_mortalite pour l’axe X et tableau_tests pour l’axe Y. Chaque
pays devient un point dont la position reflète ces deux variables.
• s=tailles_points définit la taille de chaque marqueur selon le tableau calculé plus haut.
Les pays avec beaucoup de cas apparaîtront en grosses bulles, ceux avec peu de cas en
petites bulles.
• c=tableau_mortalite définit la couleur de chaque marqueur selon la mortalité. Associé
à cmap=’YlOrRd’ (Yellow-Orange-Red, une palette séquentielle allant du jaune pâle au
rouge intense), cela crée un dégradé : les pays à faible mortalité sont jaunes, ceux à forte
mortalité sont rouge foncé.
Note importante : la mortalité est ici encodée deux fois, par la couleur et par la position sur
l’axe X. C’est une forme de redondance visuelle, généralement déconseillée car elle gaspille
une dimension visuelle. Certains auteurs préfèrent réserver la couleur pour une variable
di érente (par exemple, le continent). Mais la redondance peut aussi renforcer le message en
aidant à lire rapidement le gradient de mortalité.
alpha=0.75 rend les marqueurs légèrement transparents, essentiel quand plusieurs points
risquent de se chevaucher. edgecolors=’black’ ajoute un liseré noir qui délimite chaque
marqueur, y compris quand ils se touchent.

Barre de couleur (colorbar)

barre_couleurs = [Link](nuage_points, ax=axe, pad=0.02, shrink=0.85


barre_couleurs.set_label(‘Taux de mortalité pour 100k habitants’, fontsize=12, fontweight=’semibold’,
labelpad=10
Exemples pratiques avec Matplotlib 233

La colorbar est un élément essentiel quand on utilise cmap : sans elle, le lecteur ne saurait
pas à quelle valeur correspond chaque nuance de couleur. Elle est générée automatiquement
à partir de l’objet nuage_points et placée à droite du graphique :
• pad=0.02 : espacement entre le graphique et la barre de 2 % de la largeur.
• shrink=0.85 : la barre n’occupe que 85 % de la hauteur, ce qui évite un e et d’écrasement
visuel.

Annotation des pays remarquables

indices_top_cas = [Link](tableau_cas_confirmes)[-5:]
indice_max_mortalite = [Link](tableau_mortalite)
indice_max_tests = [Link](tableau_tests)
indices_a_annoter = set(indices_top_cas.tolist() + [indice_max_mortalite, indice_max_tests])

Avec 26 pays, annoter chaque point rendrait le graphique illisible. La solution : annoter
uniquement les points remarquables.
[Link](tableau_cas_confirmes)[-5:] est une technique courante :
• argsort() renvoie les indices qui trieraient le tableau (pas les valeurs triées elles-mêmes).
• [-5:] prend les 5 derniers, correspondant aux 5 valeurs les plus élevées.
[Link]() renvoie directement l’indice de la valeur maximum.
set(...) convertit la liste en ensemble pour éliminer les doublons : un pays peut apparaître à
la fois dans le top 5 et avoir aussi la mortalité maximum, auquel cas on ne veut pas l’annoter
deux fois.

for indice in indices_a_annoter:


[Link](
tableau_pays[indice],
xy=(tableau_mortalite[indice], tableau_tests[indice]),
xytext=(10, 10, textcoords=’offset points’,
fontsize=12, fontweight=’bold’, color=’navy’,
bbox=dict(boxstyle=’round,pad=0.5’, facecolor=’white’, edgecolor=’black’, alpha=0.85,
zorder=6
)

La boucle annotate() place une bulle blanche encadrée à proximité de chaque pays
remarquable, décalée de 10 pixels en haut à droite du point. Cette technique d’annotation
sélective est essentielle pour conserver la lisibilité dans un graphique dense.
234 Exemples pratiques avec Matplotlib

Lignes de référence médianes

mediane_mortalite = [Link](tableau_mortalite)
mediane_tests = [Link](tableau_tests)
[Link](mediane_mortalite, color=’orange’, linestyle=’--’, linewidth=2.0, alpha=0.6, zorder=2
[Link](mediane_tests, color=’orange’, linestyle=’--’, linewidth=2.0, alpha=0.6, zorder=2

Les deux lignes médianes (une verticale, une horizontale) divisent le graphique en quatre
quadrants, technique classique en analyse exploratoire :
• En haut à droite : pays à mortalité et tests élevés.
• En bas à droite : pays à mortalité élevée mais peu de tests (situation préoccupante).
• En haut à gauche : pays à faible mortalité et beaucoup de tests (situation enviable).
• En bas à gauche : pays à faible mortalité et peu de tests.
Cette segmentation visuelle aide à identifier des profils pays.

[Link](mediane_mortalite + 1, axe.get_ylim()[1 * 0.98,


f’ Médiane mortalité : {mediane_mortalite:.1f}’,
rotation=90, va=’top’, ha=’left’, fontsize=12, color=’black’, style=’italic’)

Un texte pivoté à 90° (rotation=90) annote la ligne verticale. axe.get_ylim()[1] récupère la valeur
maximale de l’axe Y pour placer le texte en haut de la ligne, le multiplicateur 0.98 laissant une
petite marge avec le bord supérieur.

Échelle logarithmique sur Y

axe.set_yscale(‘log’)

C’est un choix crucial dans ce graphique. L’axe Y représente les tests quotidiens, qui varient de
8 à 24 988, soit près de 4 ordres de grandeur. Sur une échelle linéaire, les petits pays (Islande :
10 tests) seraient écrasés au bas du graphique, indiscernables les uns des autres, tandis que
les États-Unis domineraient tout.
L’échelle logarithmique compresse les grandes valeurs et étire les petites : chaque graduation
représente une multiplication par 10 (10, 100, 1000, 10 000). Résultat : la dispersion entre
pays devient lisible à toutes les échelles.
Quand utiliser une échelle log ?
• Quand les données couvrent plusieurs ordres de grandeur (facteur 100, 1000 ou plus).
• Quand les variations relatives importent plus que les variations absolues (passer de 10 à
100 est équivalent à passer de 1000 à 10 000 en termes de croissance).
Exemples pratiques avec Matplotlib 235
• En finance, démographie, biologie, sismologie, où les phénomènes sont souvent
multiplicatifs.
• Précaution : une échelle logarithmique trompe facilement un lecteur non averti. Il faut
impérativement l’indiquer dans le titre de l’axe, comme ici (échelle log).

Titre, labels, grille et bordures

axe.set_title("Pandémie de Coronavirus : mortalité vs cas confirmés quotidiens", ...)


axe.set_xlabel("Taux de mortalité pour 100 000 habitants", ...)
axe.set_ylabel("Cas confirmés quotidiens (echelle log)", ...)
[Link](True, which=’major’, linestyle=’--’, alpha=0.4, zorder=0, color=’grey’)
[Link](True, which=’minor’, linestyle=’:’, alpha=0.15, zorder=0, color=’grey’)

Configuration standard : titre, labels d’axes, grille à deux niveaux (majeure et mineure).
L’échelle logarithmique active automatiquement des graduations mineures (les valeurs 20,
30, 40… entre 10 et 100 par exemple), utiles pour lire finement les valeurs.

Légende personnalisée pour les tailles

valeurs_reference = [100_000, 1_000_000, 5_000_000


legendes_taille = []
for valeur in valeurs_reference:
taille_normalisee = (valeur - tableau_cas_confirmes.min()) / \
(tableau_cas_confirmes.max() - tableau_cas_confirmes.min())
taille_affichee = taille_normalisee * (taille_max - taille_min) + taille_min
cercle = [Link]([], [], s=taille_affichee,
color=’lightgray’, edgecolors=’black’, linewidths=1.2,
alpha=0.75, label=f’ {valeur:,} cas’.replace(‘,’, ‘ ‘))
legendes_taille.append(cercle)

C’est une technique avancée. Par défaut, Matplotlib ne produit pas de légende pour les tailles
variables, la colorbar documente la couleur, mais rien ne documente la taille. Il faut donc
fabriquer manuellement des entrées de légende.
L’astuce : on trace des scatters invisibles ([], [] comme coordonnées, donc aucun point
tracé) avec des tailles calibrées sur des valeurs de référence (100 000, 1 million, 5 millions
de cas). Ces scatters vides servent uniquement d’échantillons visuels pour la légende. La
séparation des milliers en format français (replace(‘,’, ‘ ‘)) est à nouveau utilisée pour respecter
la convention typographique.
236 Exemples pratiques avec Matplotlib

legende = [Link](handles=legendes_taille, loc=’center’,


title=’Taille du marqueur (total des cas confirmés)’, ... )

La légende est placée sous le graphique via bbox_to_anchor, sur 3 colonnes pour a icher
les trois tailles de référence côte à côte. Le paramètre labelspacing=2.5 et borderpad=2.5
augmentent les espacements internes, car les cercles de référence sont volumineux et ont
besoin d’air autour d’eux.

Encadré statistique

texte_stats = (f"Pays analyses : {len(tableau_pays)}\n"


f"Total cas : {tableau_cas_confirmes.sum():,}".replace(‘,’, ‘ ‘) + "\n"
f"Mortalite moyenne : {tableau_mortalite.mean():.1f}\n"
f"Tests quotidiens moyens : {tableau_tests.mean():.0f}")
[Link](0.4, 0.2, texte_stats, transform=[Link], ...)

Quatre statistiques synthétiques dans un encadré monospace placé en coordonnées


relatives (40 % en largeur, 20 % en hauteur). Le replace(‘,’, ‘ ‘) formate à nouveau les nombres
à la française.

Sauvegarde et aƯichage

# affichage
plt.tight_layout()
[Link]("f14/graphique_12.png", facecolor=’oldlace’, bbox_inches=’tight’, dpi=300
[Link]()

Ajustement automatique, sauvegarde et a ichage.

Résultat attendu

Un nuage de points riche avec :


• 26 bulles de tailles variables (selon les cas confirmés).
• Des couleurs graduées du jaune au rouge (selon la mortalité).
• Les pays les plus importants annotés en bulles blanches encadrées.
• Deux lignes médianes orange segmentant l’espace en quadrants.
• Un axe Y logarithmique permettant de lire les petites et grandes valeurs.
• Une barre de couleur à droite expliquant le dégradé.
• Une légende personnalisée sous le graphique expliquant la taille des marqueurs.
• Un encadré statistique synthétique.
Exemples pratiques avec Matplotlib 237

Lecture du graphique

Quelques observations typiques tirées de ce type de représentation :


• Les États-Unis devraient apparaître en gros point en haut à droite (beaucoup de tests,
forte mortalité, beaucoup de cas).
• Des pays comme l’Islande, la Nouvelle-Zélande, Singapour devraient apparaître en petits
points jaunes en bas à gauche (peu de cas, faible mortalité, peu de tests).
• Le Pérou (mortalité = 83.3, la plus élevée) dominera visuellement sur l’axe horizontal.
• La forme générale du nuage indique-t-elle une corrélation entre tests et mortalité ? C’est
à l’œil du lecteur d’interpréter

Quand utiliser un nuage de points multidimensionnel ?

Ce type de graphique est particulièrement adapté quand :


• On a de nombreuses entités (pays, entreprises, produits) à comparer.
• On veut explorer visuellement des relations entre 3 ou 4 variables.
• Les données couvrent des ordres de grandeur très di érents (d’où l’échelle log).
• Le public est relativement expérimenté en lecture de visualisations.
Limites à connaître :
• Au-delà de 4 dimensions encodées, le graphique devient di icile à lire.
• Les marqueurs qui se chevauchent peuvent masquer des points (d’où l’importance de la
transparence).
• Les échelles logarithmiques trompent les lecteurs non avertis s’ils ne sont pas clairement
signalées.
• La taille des bulles est notoirement mal perçue : un cercle 4 fois plus grand que l’autre en
surface paraît seulement environ 2 fois plus grand à l’œil. Il faut donc doser les contrastes
de taille avec prudence.
• La redondance couleur/position (ici mortalité encodée deux fois) est un choix discutable
car elle renforce le message au prix d’une dimension visuelle gaspillée.

Les concepts clés à retenir

Ce code illustre plusieurs techniques transposables :


• La normalisation min-max vers un intervalle visuel exploitable, réflexe indispensable dès
qu’une variable doit moduler une propriété graphique.
• L’annotation sélective via argsort() et argmax() + ensemble pour dédoublonner, stratégie
essentielle dans les graphiques denses.
• L’échelle logarithmique pour les données multi-ordres, toujours signalée dans le label de
l’axe.
• La légende fabriquée manuellement avec des scatters vides, technique puissante pour
documenter les dimensions visuelles que Matplotlib ne gère pas automatiquement
238 Exemples pratiques avec Matplotlib

(taille, opacité, style de marqueur).


• La segmentation par médianes en quadrants, outil d’analyse exploratoire simple mais
très éclairant pour catégoriser visuellement des entités.
• L’association systématique cmap + colorbar, ne jamais utiliser une palette de couleurs
sans fournir sa légende de décodage.

13 - Surface 3D

Dans ce paragraphe, on compose une surface tridimensionnelle (figure 13) représentant une
fonction mathématique à symétrie radiale, enrichie de projections de contours sur les trois
plans (sol et deux murs) pour mieux appréhender sa géométrie. C’est un exemple typique de
visualisation 3D scientifique.

from mpl_toolkits.mplot3d import Axes3D


[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’})
# Fonction mathematique
def calculer_cote(valeur_x, valeur_y):
"""Calcule z = sin(sqrt(x² + y²)), surface en vagues concentriques."""
return [Link]([Link](valeur_x ** 2  valeur_y ** 2
# Grille fine pour un rendu lisse
resolution_grille = 120
abscisses_grille = [Link](-6, 6, resolution_grille)
ordonnees_grille = [Link](-6, 6, resolution_grille)
grille_x, grille_y = [Link](abscisses_grille, ordonnees_grille)
grille_z = calculer_cote(grille_x, grille_y)
# Figure haute resolution
figure = [Link](figsize=(13, 9, dpi=300, facecolor=’lightblue’)
axe_3d = figure.add_subplot(111, projection=’3d’)
axe_3d.set_facecolor(‘lightblue’)
# Surface 3D avec palette perceptuellement uniforme
surface = axe_3d.plot_surface(
grille_x, grille_y, grille_z,
cmap=’viridis’,
edgecolor=’none’,
alpha=0.92,
antialiased=True,
linewidth=0,
rcount=resolution_grille,
Exemples pratiques avec Matplotlib 239
ccount=resolution_grille
)
# Projections de contours sur les 3 plans (sol + 2 murs)
# Sol (z = -1.5
axe_3d.contourf(grille_x, grille_y, grille_z, zdir=’z’, offset=-1.5, cmap=’viridis’, alpha=0.6, levels=20
# Mur gauche (x = -7
axe_3d.contour(grille_x, grille_y, grille_z, zdir=’x’, offset=-7, cmap=’viridis’, alpha=0.4, levels=10
# Mur arriere (y = 7
axe_3d.contour(grille_x, grille_y, grille_z, zdir=’y’, offset=7, cmap=’viridis’, alpha=0.4, levels=10
# Angle de vue optimise
axe_3d.view_init(elev=28, azim=-55

Figure n°13
240 Exemples pratiques avec Matplotlib

# Bornes etendues pour accueillir les projections


axe_3d.set_xlim(-7, 6
axe_3d.set_ylim(-6, 7
axe_3d.set_zlim(-1.5, 1.2
# Labels des axes
axe_3d.set_xlabel(‘Axe X’, fontweight=’bold’, labelpad=12
axe_3d.set_ylabel(‘Axe Y’, fontweight=’bold’, labelpad=12
axe_3d.set_zlabel(‘Z  sin(√(x² + y²))’, fontweight=’bold’, labelpad=12
# Titre
axe_3d.set_title("Surface 3D  Fonction à symétrie radiale",
fontsize=22, fontweight=’bold’, pad=20, color=’navy’)
# Stylisation des panneaux (murs 3D
axe_3d.[Link].set_facecolor(‘white’)
axe_3d.[Link].set_facecolor(‘white’)
axe_3d.[Link].set_facecolor(‘white’)
for pane in [axe_3d.[Link], axe_3d.[Link], axe_3d.[Link]]:
pane.set_edgecolor(‘black’)
pane.set_alpha(1.0)
# Grille et graduations
axe_3d.grid(True, linestyle=’--’, alpha=0.3
axe_3d.tick_params(labelsize=12, colors=’red’)
# Barre de couleur
barre_couleurs = [Link](surface, ax=axe_3d, pad=0.12, shrink=0.65, aspect=25
barre_couleurs.set_label(‘Valeur de Z’, fontsize=14, fontweight=’bold’, labelpad=12
barre_couleurs.ax.tick_params(labelsize=12
barre_couleurs.outline.set_edgecolor(‘black’)
# Encadre d’information mathematique
texte_info = (f"Fonction : z = sin(√(x² + y²))\n"
f"Domaine : x, y - [-6, 6\n"
f"Resolution : {resolution_grille}x{resolution_grille} points\n"
f"Z min/max : {grille_z.min():+.2f} / {grille_z.max():+.2f}")
[Link](0.03, 0.90, texte_info,
fontsize=12, family=’monospace’,
verticalalignment=’top’, horizontalalignment=’left’,
bbox=dict(boxstyle=’round,pad=0.8’, facecolor=’whitesmoke’, edgecolor=’red’, alpha=1.0
# Source
[Link](0.02, 0.02, "Graphique généré avec Matplotlib (mpl_toolkits.mplot3d)",
Exemples pratiques avec Matplotlib 241
fontsize=12, style=’italic’, color=’gray’)
# affichage
plt.tight_layout()
[Link]("f14/graphique_13.png",facecolor=’lightblue’,bbox_inches=’tight’,dpi=300
[Link]()

Particularité : le graphique de surface 3D avec projections

C’est la grande nouveauté de ce graphique. Jusqu’ici tous les exemples étaient en 2D.
Matplotlib propose le module dédié mpl_toolkits.mplot3d permettant de tracer des objets
dans un espace à trois dimensions :
• Surfaces via plot_surface().
• Courbes 3D via plot().
• Nuages de points 3D via scatter().
• Contours projetés via contour() et contourf().
Ce code combine plusieurs de ces techniques pour o rir une vision complète d’une fonction
de deux variables d’équation Z = f(X, Y). L’astuce pédagogique est la projection des contours
sur les trois plans, qui permet de lire la même information sous trois angles di érents
simultanément.

Définition de la fonction mathématique

def calculer_cote(valeur_x, valeur_y):


"""Calcule z = sin(sqrt(x² + y²)), surface en vagues concentriques."""
return [Link]([Link](valeur_x 2  valeur_y 2

La fonction mathématique est z = sin(√(x² + y²)). Sa particularité :


• La distance à l’origine est calculée via √(x² + y²) (théorème de Pythagore). Cette valeur ne
dépend que de la distance au centre, pas de la direction, c’est la définition d’une fonction
à symétrie radiale.
• Le sinus de cette distance crée des oscillations périodiques. Résultat visuel : une surface
en vagues concentriques ressemblant aux ondulations produites par une pierre tombant
dans l’eau. C’est un grand classique de la visualisation mathématique, utilisé dans
quasiment tous les manuels d’introduction à la 3D.

Création de la grille de points

resolution_grille = 120
abscisses_grille = [Link](-6, 6, resolution_grille)
242 Exemples pratiques avec Matplotlib

ordonnees_grille = [Link](-6, 6, resolution_grille)


grille_x, grille_y = [Link](abscisses_grille, ordonnees_grille)
grille_z = calculer_cote(grille_x, grille_y)

C’est une étape technique fondamentale pour toute visualisation de surface. La résolution de
120 signifie qu’on aura 120 × 120 = 14 400 points sur la grille. Plus la résolution est élevée, plus
la surface apparaît lisse, mais plus le calcul est coûteux. 120 est un bon compromis qualité/
performance pour un rendu haute définition.
[Link]() est la fonction clé : elle transforme deux tableaux 1D (x et y) en deux tableaux 2D
représentant toutes les combinaisons possibles. Si x = [1, 2, 3] et y = [4, 5], alors :
• grille_x sera [[1, 2, 3], [1, 2, 3]] (x répété pour chaque ligne).
• grille_y sera [[4, 4, 4], [5, 5, 5]] (y répété pour chaque colonne).
Résultat : chaque point (grille_x[i, j], grille_y[i, j]) représente une coordonnée unique du plan.
C’est la structure attendue par les fonctions 3D.
grille_z = calculer_cote(grille_x, grille_y) : grâce au calcul vectorisé de NumPy, la fonction
s’applique en une seule opération sur tous les points de la grille. Pas besoin de boucle
explicite, ce qui serait bien plus lent.

Création de la figure 3D

figure = [Link](figsize=(13, 9, dpi=300, facecolor=’lightblue’)


axe_3d = figure.add_subplot(111, projection=’3d’)
axe_3d.set_facecolor(‘lightblue’)

Le paramètre projection=’3d’ est la clé du passage en 3D. Sans lui, add_subplot() créerait un
axe 2D classique.
add_subplot(111) signifie grille 1×1 en position 1, c’est-à-dire un seul axe occupant toute la
figure. C’est une syntaxe abrégée équivalente à add_subplot(1, 1, 1).

Le tracé de la surface

surface = axe_3d.plot_surface(
grille_x, grille_y, grille_z,
cmap=’viridis’,
edgecolor=’none’,
alpha=0.92,
antialiased=True,
linewidth=0,
Exemples pratiques avec Matplotlib 243
rcount=resolution_grille,
ccount=resolution_grille
)

C’est le cœur du graphique. Plusieurs paramètres méritent une explication. cmap=’viridis’ est
la palette de couleurs viridis est un choix réfléchi. Elle est :
• Perceptuellement uniforme (les variations de couleur correspondent à des variations
équivalentes de valeur pour l’œil humain).
• Accessible aux daltoniens.
• Lisible en noir et blanc (la luminosité varie monotonement).
Ces trois propriétés en font le choix recommandé par la communauté data viz pour encoder
des valeurs continues.
edgecolor=’none’ et linewidth=0 : désactivent le maillage visible entre les polygones de la
surface. Sans cela, on verrait le quadrillage de 120×120 mailles, ce qui est parfois souhaité
(aspect filaire) mais souvent trop chargé visuellement.
alpha=0.92 : une transparence très légère (8 %) qui adoucit la surface sans compromettre sa
visibilité.
antialiased=True : active le lissage des bords, évitant l’e et escalier (crénelage) sur les
contours.
rcount=resolution_grille, ccount=resolution_grille : contrôlent respectivement le nombre de
lignes (rows) et de colonnes (columns) e ectivement rendues. Par défaut, Matplotlib limite
ces valeurs à 50 pour des raisons de performance, ce qui sous-échantillonnerait notre grille
120×120. En forçant ces paramètres à 120, on exploite la résolution complète de la grille.

Projections de contours sur les trois plans


C’est la technique pédagogique remarquable de ce graphique. Plutôt que de se contenter de
la surface 3D, le code projette des contours de niveau sur le sol et deux murs du boîtier 3D.

# Sol (z = -1.5
axe_3d.contourf(grille_x, grille_y, grille_z, zdir=’z’, offset=-1.5, cmap=’viridis’, alpha=0.6, levels=20

contourf() trace des contours remplis (version remplie de contour()). Les paramètres
spécifiques 3D sont :
• zdir=’z’ indique que les contours sont projetés sur un plan perpendiculaire à l’axe Z, c’est-
à-dire sur un plan horizontal (le sol).
• o set=-1.5 fixe la position de ce plan en Z. Ici, à -1.5 (en-dessous de la valeur minimale de
la fonction, qui est -1).
• levels=20 découpe la plage de valeurs en 20 zones de couleur, produisant un dégradé de
type carte topographique.
244 Exemples pratiques avec Matplotlib

Le résultat : au sol, on voit des anneaux concentriques colorés révélant la structure radiale de
la fonction vue d’en haut, comme une vue satellite.

# Mur gauche (x = -7


axe_3d.contour(grille_x, grille_y, grille_z, zdir=’x’, offset=-7, cmap=’viridis’, alpha=0.4, levels=10
# Mur arriere (y = 7
axe_3d.contour(grille_x, grille_y, grille_z, zdir=’y’, offset=7, cmap=’viridis’, alpha=0.4, levels=10

Même logique pour les deux murs, avec zdir=’x’ et zdir=’y’ pour projeter sur des plans
perpendiculaires à X et Y. L’utilisation de contour() (sans f) trace des lignes de niveau plutôt
que des zones remplies, pour un rendu plus discret sur les murs.
Ces trois projections sont la signature pédagogique de ce graphique : elles permettent de
comprendre la surface non seulement en 3D, mais aussi à travers ses profils 2D sous trois
angles. En analyse mathématique, c’est équivalent à observer les coupes de la fonction selon
chaque axe.

Réglage de l’angle de vue

axe_3d.view_init(elev=28, azim=-55

view_init() est une méthode spécifique aux axes 3D qui contrôle l’angle de la caméra :
• elev=28 : l’élévation (hauteur de la caméra) en degrés. 0° correspondrait à une vue de face
(hauteur d’œil d’un observateur), 90° à une vue du dessus. 28° o re un compromis : on
voit à la fois le relief et le sol.
• azim=-55 : l’azimut (rotation autour de l’axe vertical) en degrés. Cette valeur détermine de
quel côté on regarde l’objet. -55° oriente la caméra pour révéler à la fois les projections
sur le mur gauche et sur le mur arrière.
Le choix de l’angle est crucial en 3D : un mauvais angle peut complètement masquer les
informations importantes.

Bornes étendues pour les projections

axe_3d.set_xlim(-7, 6
axe_3d.set_ylim(-6, 7
axe_3d.set_zlim(-1.5, 1.2

Les bornes sont asymétriques pour une bonne raison : il faut laisser de la place aux projections
en dehors de la surface principale. On a :
• X s’étend de -7 à 6 : le -7 correspond au mur gauche (x = -7).
Exemples pratiques avec Matplotlib 245
• Y s’étend de -6 à 7 : le 7 correspond au mur arrière (y = 7).
• Z s’étend de -1.5 à 1.2 : le -1.5 correspond au sol.
Sans cet élargissement, les projections seraient tracées en dehors du volume visible et
n’apparaîtraient pas.

Labels des axes avec formatage mathématique

axe_3d.set_xlabel(‘Axe X’, fontweight=’bold’, labelpad=12


axe_3d.set_ylabel(‘Axe Y’, fontweight=’bold’, labelpad=12
axe_3d.set_zlabel(‘Z  sin(√(x² + y²))’, fontweight=’bold’, labelpad=12

set_zlabel() est spécifique au 3D : il n’existe pas en 2D. L’étiquette Z contient la formule


mathématique complète avec des caractères Unicode (√, ²). Le paramètre labelpad=12
augmente l’espacement, important en 3D où les labels peuvent chevaucher les graduations
si trop proches.

Stylisation des panneaux 3D

axe_3d.[Link].set_facecolor(‘white’)
axe_3d.[Link].set_facecolor(‘white’)
axe_3d.[Link].set_facecolor(‘white’)
for pane in [axe_3d.[Link], axe_3d.[Link], axe_3d.[Link]]:
pane.set_edgecolor(‘black’)
pane.set_alpha(1.0)

Les panneaux (panes) sont les trois murs gris qui forment le boîtier 3D par défaut. Ce code :
• Les blanchit pour contraster avec le fond lightblue extérieur.
• Leur ajoute un contour noir pour bien les délimiter.
• Les rend totalement opaques.
Cette personnalisation clarifie la structure géométrique du repère, facilitant la perception de
la 3D.

Barre de couleur

barre_couleurs = [Link](surface, ax=axe_3d, pad=0.12, shrink=0.65, aspect=25


barre_couleurs.set_label(‘Valeur de Z’, fontsize=14, fontweight=’bold’, labelpad=12
barre_couleurs.ax.tick_params(labelsize=12
barre_couleurs.outline.set_edgecolor(‘black’)
246 Exemples pratiques avec Matplotlib

La barre de couleur est essentielle pour décoder les nuances de viridis en valeurs numériques
de Z. Nouveauté : aspect=25 contrôle le ratio largeur/hauteur de la barre (25 signifie 25 fois
plus haute que large, donc une barre fine et élancée). outline.set_edgecolor(‘black’) ajoute un
contour noir autour de la barre.

Encadré d’information mathématique

texte_info = (f"Fonction : z = sin(√(x² + y²))\n"


f"Domaine : x, y B 6, 6\n"
f"Resolution : {resolution_grille}x{resolution_grille} points\n"
f"Z min/max : {grille_z.min():+.2f} / {grille_z.max():+.2f}")
[Link](0.03, 0.90, texte_info, ...)

Un encadré en haut à gauche récapitule les caractéristiques mathématiques : la fonction,


le domaine, la résolution et les extrêmes de Z calculés dynamiquement. Le symbole B
(appartient à) et les caractères mathématiques Unicode donnent un rendu proche de la
notation mathématique manuscrite.

Sauvegarde et aƯichage

# affichage
plt.tight_layout()
[Link]("f14/graphique_13.png", facecolor=’lightblue’, bbox_inches=’tight’, dpi=300
[Link]()

Finalisation standard.

Résultat attendu

Une visualisation 3D impressionnante avec :


• Une surface centrale en forme de vagues concentriques, colorée en dégradé viridis (violet
au centre, jaune en périphérie selon la hauteur).
• Au sol, une projection remplie révélant la structure en anneaux concentriques vue d’en
haut.
• Sur les deux murs, des lignes de contour projetées révélant les coupes latérales.
• Un cadre 3D blanc avec contours noirs encadrant l’ensemble.
• Une barre de couleur verticale à droite décodant les valeurs.
• Un encadré mathématique en haut à gauche.
L’e et global est celui d’un objet mathématique dévoilé sous plusieurs angles simultanément.
Exemples pratiques avec Matplotlib 247

Quand utiliser ce type de visualisation ?

La 3D Matplotlib est adaptée quand :


• On représente une fonction de deux variables Z = f(X, Y).
• On visualise des données spatiales volumétriques (terrain, champs physiques,
distributions statistiques).
• On veut illustrer pédagogiquement un concept mathématique ou physique.
• Le public apprécie un rendu spectaculaire (présentations, couvertures de rapports).
Limites à connaître :
• La lecture précise des valeurs est di icile en 3D (d’où l’intérêt des projections qui
reviennent à des vues 2D).
• Les zones cachées par la surface ne sont pas visibles (il faut parfois plusieurs angles de
vue ou une figure interactive).
• Le choix de l’angle impacte fortement ce que le lecteur perçoit : un mauvais angle peut
induire en erreur.
• L’interactivité est limitée dans les fichiers PNG statiques, pour une vraie exploration 3D,
des outils comme Plotly, Bokeh, Mayavi ou PyVista o rent la rotation à la souris.
• En général, les experts en data viz recommandent d’éviter la 3D pour les données
analytiques, préférant les vues 2D (contours, heatmaps) qui se lisent plus précisément.
La 3D est surtout justifiée en pédagogie et en communication visuelle.

Les concepts clés à retenir

Ce code illustre plusieurs techniques transposables :


• La grille meshgrid() est indispensable pour toute fonction de deux variables : elle
transforme deux axes en un plan complet de coordonnées, sur lequel NumPy peut
appliquer des calculs vectorisés e icacement.
• Les projections de contours (contour(), contourf() avec zdir et o set) enrichissent
considérablement une surface 3D en o rant des coupes 2D intégrées. C’est un pattern
très pédagogique.
• Le choix de la palette viridis (ou magma, plasma, cividis) est une bonne pratique moderne
pour les données continues, bien préférable aux anciennes palettes jet ou rainbow, qui
trahissent les valeurs par des variations de luminosité non uniformes.
• Le réglage manuel de l’angle de vue avec view_init() est capital : tester plusieurs
combinaisons (elev, azim) pour trouver celle qui révèle le mieux la structure des données.
• L’extension des bornes pour accueillir les projections : en 3D, il faut penser que
les éléments graphiques peuvent exister hors de la zone de données principale, et
dimensionner le volume en conséquence.
248 Exemples pratiques avec Matplotlib

14 - Carte de chaleur

Dans ce paragraphe, on compose une carte de chaleur (heatmap) représentant l’évolution


hebdomadaire des consultations médicales pour quatre symptômes sur neuf semaines
(figure 14). Chaque cellule colorée exprime un pourcentage, avec des annotations chi rées à
l’intérieur et une couleur de texte qui s’adapte automatiquement au fond.
Figure n°14

[Link]({ ‘[Link]’:’Roboto Condensed’, ‘[Link]’:’16’})


# Donnees
liste_symptomes = ["Coronavirus", "Grippe", "Pneumonie", "Dyspnee"]
liste_dates = ["28 Jun", "05 Jul", "12 Jul", "19 Jul", "26 Jul",
"02 Aou", "09 Aou", "16 Aou", "21 Aou"]
pourcentages_symptomes = [Link]([
5.2, 5.5, 5.7, 5.6, 5.3, 5.1, 5.0, 4.9, 5.3,
3.5, 4.0, 4.3, 3.9, 3.5, 3.2, 2.7, 2.2, 2.0,
1.8, 2.2, 2.3, 2.2, 2.1, 1.9, 1.7, 1.4, 1.3,
1.0, 1.1, 1.1, 1.0, 0.9, 0.8, 0.8, 0.8, 0.7
])
# Figure haute resolution
figure, axe = [Link](figsize=(13, 6, dpi=300, facecolor=’lavender’)
# Carte de chaleur avec palette sequentielle
Exemples pratiques avec Matplotlib 249
image_chaleur = [Link](
pourcentages_symptomes,
cmap=’YlOrRd’,
aspect=’auto’,
interpolation=’nearest’
)
# barre de couleur stylisee
barre_couleurs = [Link](image_chaleur, ax=axe, pad=0.02, shrink=0.9, aspect=20
barre_couleurs.set_label(‘Pourcentage de consultations (%’, fontsize=12, fontweight=’bold’,
labelpad=12
barre_couleurs.ax.tick_params(labelsize=12
barre_couleurs.outline.set_edgecolor(‘black’)
barre_couleurs.outline.set_linewidth(0.8)
# Graduations principales
axe.set_xticks([Link](len(liste_dates)))
axe.set_yticks([Link](len(liste_symptomes)))
axe.set_xticklabels(liste_dates)
axe.set_yticklabels(liste_symptomes, fontweight=’bold’)
[Link](axe.get_xticklabels(), rotation=30, ha=’right’, rotation_mode=’anchor’,fontsize=14
# Graduations mineures pour les separations entre cellules=
axe.set_xticks([Link](len(liste_dates) + 1)  0.5, minor=True)
axe.set_yticks([Link](len(liste_symptomes) + 1)  0.5, minor=True)
[Link](which=’minor’, color=’white’, linestyle=’-’, linewidth=3
axe.tick_params(which=’minor’, bottom=False, left=False)
axe.tick_params(which=’major’, bottom=False, left=False)
# Annotations avec couleur adaptative (blanc sur fond fonce, noir sur clair)
seuil_contraste = pourcentages_symptomes.max() * 0.55
for indice_ligne in range(len(liste_symptomes)):
for indice_colonne in range(len(liste_dates)):
valeur = pourcentages_symptomes[indice_ligne, indice_colonne]
couleur_texte = ‘white’ if valeur > seuil_contraste else ‘black’
[Link](indice_colonne, indice_ligne, f’{valeur:.1f}%’, ha=’center’, va=’center’,
color=couleur_texte, fontsize=12, fontweight=’bold’)
# Titre et sous-titre
axe.set_title("Evolution hebdomadaire des consultations par symptôme",
fontsize=22, fontweight=’bold’, pad=20, color=’navy’)
[Link](0.5, 0.89,
250 Exemples pratiques avec Matplotlib

"Pourcentage de consultations médicales par type de symptôme, semaine par semaine",


ha=’center’, fontsize=10, style=’italic’, color=’red’)
# Labels des axes
axe.set_xlabel("Semaine de consultation", fontweight=’bold’, labelpad=12
axe.set_ylabel("Symptôme", fontweight=’bold’, labelpad=12
# Epuration des bordures
for position in [‘top’, ‘right’, ‘bottom’, ‘left’]:
[Link][position].set_visible(False)
# Encadre statistique
indice_max = np.unravel_index(pourcentages_symptomes.argmax(), pourcentages_symptomes.shape)
indice_min = np.unravel_index(pourcentages_symptomes.argmin(), pourcentages_symptomes.shape)
texte_stats = (f"Pic observe : {pourcentages_symptomes.max():.1f}% "
f"({liste_symptomes[indice_max[0]]}, {liste_dates[indice_max[1]]})\n"
f"Minimum observe : {pourcentages_symptomes.min():.1f}% "
f"({liste_symptomes[indice_min[0]]}, {liste_dates[indice_min[1]]})\n"
f"Moyenne globale : {pourcentages_symptomes.mean():.2f}%")
[Link](0.02, 0.0, texte_stats,
fontsize=10, family=’monospace’,
verticalalignment=’bottom’, horizontalalignment=’left’,
bbox=dict(boxstyle=’round,pad=0.3’, facecolor=’white’, edgecolor=’black’, alpha=1.0
# Source
[Link](0.98, 0.02, "Données illustratives - Généré avec Matplotlib",
fontsize=12, style=’italic’, color=’gray’, ha=’right’)
# affichage
plt.tight_layout()
[Link]("f14/graphique_14.png",facecolor=’lavender’,bbox_inches=’tight’,dpi=300
[Link]()

Particularité : la carte de chaleur (heatmap)

C’est la grande nouveauté de ce graphique. Une heatmap représente une matrice de


valeurs sous forme de grille colorée, où chaque cellule est un rectangle dont la couleur
encode une valeur numérique. Les lignes et colonnes correspondent généralement à deux
variables catégorielles (ici : symptômes en lignes, semaines en colonnes). La heatmap est
particulièrement adaptée pour :
• Détecter visuellement des motifs dans une matrice dense (pics, creux, tendances
diagonales).
Exemples pratiques avec Matplotlib 251
• Comparer rapidement de nombreuses valeurs regroupées par deux critères croisés.
• Observer une évolution temporelle par catégorie.
Techniquement, Matplotlib ne propose pas de fonction heatmap() dédiée, mais utilise une
astuce élégante : a icher un tableau NumPy comme une image via imshow(). Chaque valeur
du tableau devient un pixel coloré selon une palette choisie.

Préparation des données

liste_symptomes = ["Coronavirus", "Grippe", "Pneumonie", "Dyspnee"]


liste_dates = ["28 Jun", "05 Jul", "12 Jul", "19 Jul", "26 Jul",
"02 Aou", "09 Aou", "16 Aou", "21 Aou"]
pourcentages_symptomes = [Link]([
5.2, 5.5, 5.7, 5.6, 5.3, 5.1, 5.0, 4.9, 5.3,
3.5, 4.0, 4.3, 3.9, 3.5, 3.2, 2.7, 2.2, 2.0,
1.8, 2.2, 2.3, 2.2, 2.1, 1.9, 1.7, 1.4, 1.3,
1.0, 1.1, 1.1, 1.0, 0.9, 0.8, 0.8, 0.8, 0.7
])

Les données sont organisées en matrice 4×9 :


• 4 lignes : les symptômes (Coronavirus, Grippe, Pneumonie, Dyspnée).
• 9 colonnes : les semaines (fin juin à fin août).
Chaque cellule pourcentages_symptomes[i, j] contient le pourcentage de consultations pour
le symptôme i lors de la semaine j. Cette structure matricielle est exactement ce qu’attend
une heatmap.

Création de la figure et de la carte de chaleur

figure, axe = [Link](figsize=(13, 6, dpi=300, facecolor=’lavender’)


image_chaleur = [Link](
pourcentages_symptomes,
cmap=’YlOrRd’,
aspect=’auto’,
interpolation=’nearest’
)

imshow() est la méthode clé. Conçue à l’origine pour a icher des images (matrices de pixels),
elle est détournée ici pour représenter une matrice de données numériques. Chaque valeur
devient un pixel coloré.
252 Exemples pratiques avec Matplotlib

Ses paramètres :
• cmap=’YlOrRd’ : la palette Yellow-Orange-Red, une palette séquentielle allant du jaune
pâle au rouge foncé. Ce choix est cohérent avec le contexte sanitaire : les valeurs faibles
(peu alarmantes) en jaune clair, les valeurs élevées (potentiellement préoccupantes) en
rouge intense. La progression de luminosité suit l’intensité, ce qui rend la palette intuitive.
• aspect=’auto’ : permet aux cellules de ne pas être carrées. Par défaut, imshow() fixe un
ratio 1:1, ce qui produit des pixels parfaitement carrés, adapté aux images, mais pas
toujours aux heatmaps de données où l’on veut remplir toute la zone disponible. Avec
aspect=’auto’, les cellules s’étirent automatiquement pour occuper l’espace.
• interpolation=’nearest’ : désactive le lissage entre cellules. Sans cela, imshow() tenterait
d’interpoler les couleurs entre pixels voisins, rendant les frontières floues. Pour une
heatmap, on veut des cellules nettement délimitées : ’nearest’ impose la couleur exacte
de chaque valeur, sans transition.

Barre de couleur

barre_couleurs = [Link](image_chaleur, ax=axe, pad=0.02, shrink=0.9, aspect=20


barre_couleurs.set_label(‘Pourcentage de consultations (%’,
fontsize=12, fontweight=’bold’, labelpad=12
barre_couleurs.ax.tick_params(labelsize=12
barre_couleurs.outline.set_edgecolor(‘black’)
barre_couleurs.outline.set_linewidth(0.8)

La colorbar est indispensable dans une heatmap : sans elle, le lecteur ne saurait pas à quel
pourcentage correspond chaque nuance de couleur. Elle est générée automatiquement à
partir de l’objet image_chaleur, avec un contour noir pour bien la délimiter.

Graduations principales avec étiquettes textuelles

axe.set_xticks([Link](len(liste_dates)))
axe.set_yticks([Link](len(liste_symptomes)))
axe.set_xticklabels(liste_dates)
axe.set_yticklabels(liste_symptomes, fontweight=’bold’)
[Link](axe.get_xticklabels(), rotation=30, ha=’right’, rotation_mode=’anchor’, fontsize=14

Le mécanisme est analogue aux graphiques en barres : on fixe d’abord les positions
numériques des graduations (0, 1, 2… aux indices des cellules), puis on associe à chaque
position un libellé textuel.
rotation_mode=’anchor’ est un paramètre subtil : il contrôle autour de quel point le texte
pivote. Avec ’anchor’, la rotation se fait autour du point d’ancrage défini par ha=’right’, ce qui
Exemples pratiques avec Matplotlib 253
garde la fin des étiquettes bien alignée avec les graduations, même après rotation.

Graduations mineures et séparateurs blancs

axe.set_xticks([Link](len(liste_dates) + 1)  0.5, minor=True)


axe.set_yticks([Link](len(liste_symptomes) + 1)  0.5, minor=True)
[Link](which=’minor’, color=’white’, linestyle=’-’, linewidth=3
axe.tick_params(which=’minor’, bottom=False, left=False)
axe.tick_params(which=’major’, bottom=False, left=False)

C’est une astuce très élégante pour créer des bordures blanches entre les cellules.
Décomposons :
• [Link](len(liste_dates) + 1) - 0.5 génère les positions [-0.5, 0.5, 1.5, 2.5, ...]. Ces valeurs
tombent entre deux cellules (la cellule d’indice 0 est centrée sur la position 0, elle s’étend
donc de -0.5 à 0.5).
• minor=True définit ces graduations comme mineures (distinctes des principales qui
placent les labels).
• [Link](which=’minor’, color=’white’, linestyle=’-’, linewidth=3) trace alors une grille blanche
épaisse à ces positions. Résultat : chaque cellule apparaît séparée de ses voisines par
une ligne blanche, accentuant visuellement la grille et donnant un aspect plus soigné.
• tick_params(bottom=False, left=False) masque les petits traits aux graduations (pour les
deux niveaux, mineur et majeur), rendant l’ensemble plus épuré.

Annotations avec couleur adaptative

seuil_contraste = pourcentages_symptomes.max() * 0.55


for indice_ligne in range(len(liste_symptomes)):
for indice_colonne in range(len(liste_dates)):
valeur = pourcentages_symptomes[indice_ligne, indice_colonne]
couleur_texte = ‘white’ if valeur > seuil_contraste else ‘black’
[Link](indice_colonne, indice_ligne, f’{valeur:.1f}%’, ha=’center’, va=’center’,
color=couleur_texte, fontsize=12, fontweight=’bold’)

C’est une technique particulièrement élégante de ce graphique. Écrire du texte sur une
heatmap pose un problème de lisibilité : sur les cellules très claires (jaune pâle), un texte
blanc devient invisible et sur les cellules très foncées (rouge intense), un texte noir devient
di icile à lire. La solution du seuil adaptatif :
• On calcule un seuil de contraste à 55 % de la valeur maximum.
• Si la valeur d’une cellule dépasse ce seuil (donc couleur foncée), le texte s’a iche en
blanc.
254 Exemples pratiques avec Matplotlib

• Sinon (couleur claire), le texte s’a iche en noir.


Le choix du coe icient 0.55 est empirique : il dépend de la palette utilisée et doit parfois être
ajusté. Pour YlOrRd, le milieu de palette se situe vers des tons orange moyens, et 0.55 est un
bon compromis qui maximise la lisibilité sur toute la gamme.
La double boucle parcourt toutes les cellules de la matrice et place le pourcentage formaté
au centre de chacune. Les coordonnées (indice_colonne, indice_ligne) correspondent bien à
la convention de imshow() : X est la colonne, Y est la ligne (et non l’inverse, attention à ce point
souvent source d’erreur).

Titre, sous-titre et labels

axe.set_title("Evolution hebdomadaire des consultations par symptôme",


fontsize=22, fontweight=’bold’, pad=20, color=’navy’)
[Link](0.5, 0.89,
"Pourcentage de consultations médicales par type de symptôme, semaine par semaine",
ha=’center’, fontsize=10, style=’italic’, color=’red’)
axe.set_xlabel("Semaine de consultation", fontweight=’bold’, labelpad=12
axe.set_ylabel("Symptôme", fontweight=’bold’, labelpad=12

Titre principal en bleu marine gras, sous-titre italique rouge pour préciser le contexte,
labels des deux axes. Le duo titre/sous-titre est une convention éditoriale qui hiérarchise
l’information : le titre attire l’œil, le sous-titre précise la nature exacte des données.

Bordures masquées

for position in [‘top’, ‘right’, ‘bottom’, ‘left’]:


[Link][position].set_visible(False)

Les quatre bordures sont masquées, contrairement aux graphiques précédents qui en
conservaient certaines. Pour une heatmap, cette décision fait sens : la structure matricielle
est déjà clairement délimitée par les séparateurs blancs et les cellules colorées, un cadre
supplémentaire serait redondant.

Encadré statistique avec indices multidimensionnels

indice_max = np.unravel_index(pourcentages_symptomes.argmax(), pourcentages_symptomes.shape)


indice_min = np.unravel_index(pourcentages_symptomes.argmin(), pourcentages_symptomes.shape)
texte_stats = (f"Pic observe : {pourcentages_symptomes.max():.1f}% "
f"({liste_symptomes[indice_max[0]]}, {liste_dates[indice_max[1]]})\n"
Exemples pratiques avec Matplotlib 255
f"Minimum observe : {pourcentages_symptomes.min():.1f}% "
f"({liste_symptomes[indice_min[0]]}, {liste_dates[indice_min[1]]})\n"
f"Moyenne globale : {pourcentages_symptomes.mean():.2f}%")

Une nouveauté technique importante apparaît ici :


• argmax() sur un tableau 2D renvoie un indice aplati comme si le tableau était linéaire. Par
exemple, pour une matrice 4×9, la position (2, 5) correspond à l’indice aplati 2×9+5 = 23.
Cet indice linéaire seul ne permet pas de retrouver directement la ligne et la colonne.
• np.unravel_index() est la fonction qui reconvertit cet indice aplati en coordonnées
multidimensionnelles (ligne, colonne). Elle a besoin de la forme originale du tableau
(pourcentages_symptomes.shape, soit (4, 9)) pour e ectuer cette conversion.
Résultat : indice_max est un tuple (ligne, colonne), qu’on peut utiliser pour récupérer le nom du
symptôme (liste_symptomes[indice_max[0]]) et la date (liste_dates[indice_max[1]]) associés
au pic. Cette technique est systématique quand on veut localiser des extrêmes dans une
matrice et leur associer des étiquettes descriptives. L’encadré final a iche :
• Le pic observé (valeur maximale) avec son contexte (symptôme et semaine).
• Le minimum observé avec son contexte.
• La moyenne globale sur l’ensemble de la matrice.

Source, sauvegarde et aƯichage

[Link](0.98, 0.02,
"Données illustratives - Généré avec Matplotlib",
fontsize=12, style=’italic’, color=’gray’, ha=’right’)
plt.tight_layout()
[Link]("f14/graphique_14.png", facecolor=’lavender’, bbox_inches=’tight’, dpi=300
[Link]()

Mention de source à droite cette fois (pour ne pas entrer en conflit avec l’encadré statistique
placé à gauche), puis sauvegarde et a ichage.

Résultat attendu

Une heatmap claire et informative avec :


• 4 lignes × 9 colonnes de cellules colorées selon la palette YlOrRd.
• Des séparateurs blancs épais entre cellules, donnant un aspect carrelage.
• Le pourcentage inscrit dans chaque cellule, en blanc ou noir selon le contraste.
• Une barre de couleur à droite décodant les nuances.
• Des étiquettes de dates pivotées à 30° sur l’axe X.
• Un encadré statistique en bas à gauche indiquant pic, minimum et moyenne.
256 Exemples pratiques avec Matplotlib

Lecture du graphique

La heatmap permet de lire plusieurs motifs simultanément :


• La ligne Coronavirus montre un pic rouge vers mi-juillet (5.7 %) puis une relative stabilité,
visuellement, c’est la ligne la plus intense.
• La ligne Grippe révèle une tendance nettement décroissante (passage du rouge à l’orange
pâle de gauche à droite).
• Les lignes Pneumonie et Dyspnée restent globalement en tons jaunes (valeurs faibles).
• Une tendance générale se dessine : la plupart des symptômes déclinent au fil de l’été,
sauf le Coronavirus qui reste élevé.
Cette lecture en coup d’œil des structures et tendances est l’atout principal d’une heatmap,
un tableau numérique classique ne permettrait pas de percevoir aussi rapidement ces motifs.

Quand utiliser une heatmap ?

La heatmap est particulièrement adaptée pour :


• Visualiser une matrice de corrélations (variable × variable).
• Observer des évolutions temporelles par catégorie (comme ici).
• Représenter une fréquentation croisée (jour × heure, produit × région, etc).
• A icher des matrices de confusion en machine learning.
• Explorer des motifs dans des données biologiques (heatmaps génétiques).
Limites à connaître :
• Les heatmaps fonctionnent mieux avec des matrices de taille modérée (idéalement entre
5×5 et 30×30). Au-delà, les annotations deviennent illisibles et les cellules trop petites
• La lisibilité des annotations dépend beaucoup du contraste d’où l’importance du seuil
adaptatif démontré ici
• Le choix de la palette est crucial : palette séquentielle (comme YlOrRd) pour des valeurs
positives croissantes, palette divergente (comme RdBu) quand il y a un centre naturel (0,
moyenne, seuil), palette qualitative à éviter pour des valeurs continues
• L’ordre des lignes et colonnes influe fortement sur la lisibilité. Parfois, trier par similarité
(clustering) ou par intensité décroissante révèle des motifs invisibles dans l’ordre original

Les concepts clés à retenir

Ce code illustre plusieurs techniques transposables :


• imshow() est détourné pour les heatmaps. Une fonction conçue pour les images qui
devient l’outil standard pour visualiser des matrices de valeurs, grâce aux paramètres
cmap, aspect et interpolation.
• Les graduations mineures pour créer des séparateurs : astuce élégante qui exploite le
système à deux niveaux de Matplotlib pour produire des bordures de cellules propres.
Exemples pratiques avec Matplotlib 257
• La couleur de texte adaptative : pattern essentiel dès qu’on annote des cellules colorées.
Le choix du seuil dépend de la palette et mérite parfois d’être testé visuellement.
• np.unravel_index() pour décoder les indices aplatis : technique indispensable quand on
cherche les extrêmes d’une matrice et qu’on veut récupérer leurs coordonnées (ligne,
colonne) lisibles.
• La combinaison palette séquentielle + barre de couleur + annotations : c’est le trio de
base d’une heatmap professionnelle. Chaque élément renforce l’autre : la palette donne
l’impression globale, les chi res apportent la précision, la barre sert de pont entre couleur
et valeur.
FORMATEUR
DÉVELOPPEUR
AUTEUR

Informaticien et formateur indépendant,


diplômé en informatique et certifié Microsoft MCTS.
Passionné par les technologies WPF, LINQ et DirectX, spécialiste du
langage C#, programmeur passionné des API 3D, je vous fais
partager ma passion pour le développement et la programmation
des applications informatiques au travers de mes ouvrages.

Patrice REY
4435-199 RIO TINTO
PORTUGAL
Des manuels pratiques pour apprendre à programmer
en vente dans les meilleurs points de vente

AMAZON CHAPITRE DECITRE


[Link] [Link] [Link]

FNAC CULTURA
[Link] [Link]

Informaticien et formateur indépendant,


diplômé en informatique et certifié Microsoft MCTS.
Passionné par les technologies WPF, LINQ et DirectX, spécialiste du langage C#,
programmeur passionné des API 3D, je vous fais partager ma passion pour le
développement et la programmation des applications informatiques au travers de
mes ouvrages.

AMAZON LINKEDIN
[Link]/3fXLGqa [Link]/3fe5YhD

Patrice REY
RIO TINTO - PORTUGAL
SITE WEB >> [Link]
EMAIL >> patricerey33@[Link]

Vous aimerez peut-être aussi