Matplotlib en Python : figures, axes, tracés, sous-graphiques & savefig

Construisez les figures qui ont leur place dans un rapport — le modèle Figure/Axes, les tracés essentiels, les dispositions multi-panneaux, et un export de qualité publication.

Apprenez matplotlib en Python en construisant les figures qui vont dans un vrai rapport : l’API orientée objet Figure/Axes et son lien avec plt., les tracés essentiels (courbe, nuage de points, histogramme, barres), les étiquettes, titres et légendes, les sous-graphiques multi-panneaux, un style de qualité publication, et l’export avec savefig.

Date de publication

17 juillet 2026

Modifié

18 juillet 2026

AstucePoints clés
  • Une figure est une toile ; un Axes est un tracé posé dessus. Vous dessinez sur un objet Axes (ax.plot, ax.bar, ax.set_xlabel) — ce style orienté objet est celui qui passe à l’échelle des figures multi-panneaux.
  • plt.subplots() est votre point de départ par défaut. fig, ax = plt.subplots() vous remet les deux poignées d’un coup ; demandez une grille (plt.subplots(2, 2)) et vous obtenez un panneau d’Axes.
  • Quatre tracés couvrent la plupart des rapports : scatter pour les relations, hist pour la forme d’une variable, bar pour une valeur par groupe, plot pour une tendance le long d’une variable ordonnée.
  • Étiquetez tout. Une figure sans étiquettes d’axes, sans titre ni légende est illisible pour tout autre que vous — set_xlabel, set_ylabel, set_title, legend() ne sont pas optionnels.
  • Définissez le style maison une seule fois, en amont. Quelques rcParams (pas de bordures en haut/à droite, une grille légère, une couleur de marque) transforment le gris par défaut de matplotlib en un rendu de qualité publication pour chaque figure qui suit.
  • fig.savefig("figure.png", dpi=300, bbox_inches="tight") exporte un fichier net — dpi=300 pour l’impression, bbox_inches="tight" pour rogner les marges blanches.

Introduction

Vous avez un jeu de données et une question, et il vous faut maintenant la figure qui y répond — celle qui va dans le rapport, l’article ou la diapositive. Matplotlib est le moteur qui la dessine. Presque toutes les bibliothèques de tracé Python (le .plot() de pandas, seaborn, et même certaines parties de plotly) reposent sur matplotlib, donc l’apprendre une fois est rentable partout.

Cette leçon n’est pas un tour d’horizon de chaque fonction. C’est un vrai workflow : nous chargeons une table de mesures de manchots et construisons la poignée de figures que vous utilisez réellement — un nuage de points pour voir une relation, un histogramme pour voir une distribution, un diagramme en barres pour comparer des groupes, une courbe pour montrer une tendance — puis nous les disposons ensemble, les stylons à un standard de publication, et en sauvegardons une sur le disque. Chemin faisant, vous apprenez le seul modèle mental qui fait « cliquer » matplotlib : Figure et Axes.

Les données sont un petit CSV de manchots livré à côté de cette leçon (des mesures physiques pour trois espèces), il n’y a donc rien à télécharger et aucun seaborn.load_dataset n’a besoin d’accéder au réseau. Chaque figure ci-dessous a été produite par le code montré. Les blocs s’enchaînent dans l’ordre — comme lors d’une vraie session, nous chargeons les données et fixons le style une fois, puis nous traçons. Pour expérimenter vous-même, modifiez la cellule autonome Essayez en direct à la fin et appuyez sur Run ; elle s’exécute dans votre navigateur via Pyodide.

Le modèle mental : Figure et Axes

Matplotlib vous offre deux façons de tracer, et choisir la bonne épargne des heures de confusion.

  • Les raccourcis pyplot (plt.)plt.plot(...), plt.xlabel(...) — dessinent sur ce qui est la figure « courante ». Rapide pour un usage ponctuel, mais « courante » devient ambigu dès l’instant où vous avez plus d’un panneau.
  • L’API orientée objet (OO) — vous tenez une Figure (la toile entière) et un ou plusieurs Axes (chacun un tracé individuel avec ses propres axes x/y) et vous appelez des méthodes dessus : ax.plot(...), ax.set_xlabel(...). Explicite, sans ambiguïté, et le seul style qui passe à l’échelle.

Commencez chaque figure par plt.subplots(), qui crée une Figure et un Axes ensemble et renvoie les deux :

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(6, 4))
ax.plot([1, 2, 3, 4], [10, 40, 30, 50], marker="o")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("A Figure holds one Axes here")
plt.show()

A single line-and-marker plot on one Axes — four points that rise, dip, then rise again — shown in default matplotlib style to illustrate the Figure-and-Axes model.

fig est la toile ; ax est le tracé posé dessus. Vous dessinez avec ax.plot, et vous définissez les propriétés avec les méthodes ax.set_* — remarquez le motif : plt.xlabel(...) (une fonction) devient ax.set_xlabel(...) (une méthode) dans le style OO. À partir d’ici, nous utilisons l’API OO partout, car dès l’instant où vous voulez deux tracés côte à côte, plt. seul ne sait pas les distinguer.

Définissez le style visuel maison, une fois

Les réglages par défaut de matplotlib — bordures épaisses, pas de grille, un bleu terne — se lisent comme du « matplotlib par défaut », pas comme de la « publication ». Définissez un petit bloc de rcParams une seule fois en haut d’un notebook ou d’un script, et chaque figure ensuite hérite du rendu. Nous fixons aussi une palette de marque : azur #3a86d4 pour une série unique, et un échantillon viridis adapté au daltonisme pour les données groupées (le même langage visuel que nos leçons R).

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# House style — applied to every figure that follows
plt.rcParams.update({
    "figure.figsize": (7, 4.5),
    "figure.dpi": 110,
    "axes.spines.top": False,     # drop the top/right box edges
    "axes.spines.right": False,
    "axes.grid": True,            # a light reference grid
    "grid.color": "#e6e6e6",
    "grid.linewidth": 0.8,
    "axes.axisbelow": True,       # grid behind the data, not on top
    "axes.titlesize": 13,
    "axes.titleweight": "bold",
    "legend.frameon": False,
})

AZURE = "#3a86d4"                 # brand colour for a single series

# Load the data once; later blocks reuse it
penguins = pd.read_csv("penguins.csv")

# A colourblind-safe colour per species, sampled from viridis
species = ["Adelie", "Chinstrap", "Gentoo"]
palette = dict(zip(species, plt.get_cmap("viridis")(np.linspace(0.1, 0.85, 3))))
print(penguins.shape, "rows x cols")
print(list(palette))
(344, 7) rows x cols
['Adelie', 'Chinstrap', 'Gentoo']

Deux choses à remarquer. rcParams.update(...) modifie le style global, donc il affecte chaque figure ultérieure — réglez-le et oubliez-le. Et plt.get_cmap("viridis")(np.linspace(...)) prélève trois couleurs bien distinctes et adaptées au daltonisme dans la carte viridis, que nous épinglons aux trois espèces afin qu’une espèce donnée soit de la même couleur sur chaque tracé.

Nuage de points : la relation entre deux variables

Optez pour un nuage de points quand vous voulez voir comment deux variables numériques évoluent ensemble. Ici : le bec d’un manchot devient-il plus profond à mesure qu’il s’allonge ? Nous colorons chaque point par espèce et bouclons sur les groupes afin que chacun ait sa propre couleur et son entrée de légende.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
for name, group in penguins.groupby("species"):
    ax.scatter(group["bill_length_mm"], group["bill_depth_mm"],
               label=name, color=palette[name], s=28, alpha=0.8, edgecolor="white", linewidth=0.4)

ax.set_xlabel("Bill length (mm)")
ax.set_ylabel("Bill depth (mm)")
ax.set_title("Bill length vs. depth by species")
ax.legend(title="Species")
fig.tight_layout()
plt.show()
Scatter plot of bill length in millimetres on the x-axis against bill depth in millimetres on the y-axis for 342 penguins, with points coloured by species. Adelie sit upper-left (short, deep bills), Gentoo lower-right (long, shallow bills), and Chinstrap upper-right (long, deep bills); within each species longer bills go with deeper bills, an upward slope, even though the overall cloud trends downward.
Figure 1

Lisez la figure et un piège classique saute aux yeux. Regardez le nuage entier et la profondeur du bec semble diminuer quand la longueur augmente — mais au sein de chaque espèce la pente est clairement ascendante : les becs plus longs vont avec des becs plus profonds. Ce renversement (une tendance globale négative qui en cache trois positives) est le paradoxe de Simpson, et la coloration par groupe est ce qui l’expose. Un simple nuage gris vous aurait dit l’inverse de la vérité — la raison pour laquelle nous colorons presque toujours par la variable de regroupement.

fig.tight_layout() à la fin ajuste l’espacement pour que rien ne soit tronqué ; faites-en un réflexe sur chaque figure.

Histogramme : la forme d’une variable

Un histogramme répond à « comment cette variable unique est-elle distribuée ? » — où se situe la masse, quelle est la largeur de la dispersion, y a-t-il plus d’un pic. Les bins sont le seul réglage qui compte : trop peu masque la structure, trop nombreux la transforment en bruit.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.hist(penguins["body_mass_g"].dropna(), bins=25, color=AZURE, edgecolor="white")
ax.set_xlabel("Body mass (g)")
ax.set_ylabel("Number of penguins")
ax.set_title("Distribution of penguin body mass")
fig.tight_layout()
plt.show()
Histogram of penguin body mass in grams across 342 penguins using 25 bins, ranging from about 2700 to 6300 grams, with two humps: a tall cluster around 3500 to 4000 grams and a second broader cluster around 5000 grams.
Figure 2

La forme est parlante : deux bosses, pas une. Un amas élevé se situe autour de 3500–4000 g (les manchots Adelie et Chinstrap plus petits) et un second amas, plus large, se rassemble près de 5000 g (les Gentoo plus grands). Une moyenne unique d’environ 4200 g aurait masqué cette scission — l’histogramme est ce qui révèle que la population est en réalité deux groupes. Notez le .dropna() : matplotlib produit une erreur sur les NaN, alors écartez les deux manchots à la masse manquante avant de tracer.

Barres : une valeur par groupe

Un diagramme en barres compare un résumé unique — une moyenne, un effectif, un total — entre catégories. Calculez d’abord le résumé avec pandas, puis passez les nombres à ax.bar.

import matplotlib.pyplot as plt

mean_mass = penguins.groupby("species")["body_mass_g"].mean()

fig, ax = plt.subplots()
ax.bar(mean_mass.index, mean_mass.values, color=AZURE)
ax.set_xlabel("Species")
ax.set_ylabel("Mean body mass (g)")
ax.set_title("Mean body mass by species")
# Label each bar with its value
for i, v in enumerate(mean_mass.values):
    ax.text(i, v + 40, f"{v:.0f}", ha="center", va="bottom", fontsize=9)
fig.tight_layout()
plt.show()
Bar chart of mean body mass in grams for three penguin species. Adelie about 3701 grams and Chinstrap about 3733 grams are nearly equal, while Gentoo stands clearly taller at about 5076 grams.
Figure 3

Adelie (~3701 g) et Chinstrap (~3733 g) sont pratiquement à égalité ; Gentoo domine les deux à ~5076 g. La petite boucle ax.text inscrit chaque valeur au sommet de sa barre — une touche discrète qui transforme un graphique qu’il faut plisser les yeux pour lire en un graphique qui se lit exactement. Gardez les diagrammes en barres honnêtes : laissez l’axe des y commencer à zéro pour que les hauteurs des barres soient proportionnelles aux valeurs.

Courbe : une tendance le long d’une variable ordonnée

Un graphique en courbes relie des points dans l’ordre, c’est donc le bon choix quand l’axe des x est ordonné ou continu — le temps, une dose, ou ici, une mesure regroupée en bins. La table des manchots n’a pas de colonne temporelle, et c’est là tout l’intérêt : une courbe est faite pour un x ordonné, alors nous regroupons la longueur de la nageoire en bins et relions la masse corporelle moyenne de chaque bin pour tracer comment la masse grimpe avec la taille de la nageoire.

import matplotlib.pyplot as plt

p = penguins.dropna(subset=["flipper_length_mm", "body_mass_g"])
bins = pd.cut(p["flipper_length_mm"], bins=np.arange(170, 240, 10))
trend = p.groupby(bins, observed=True)["body_mass_g"].mean()
centres = [interval.mid for interval in trend.index]

fig, ax = plt.subplots()
ax.plot(centres, trend.values, marker="o", color=AZURE, linewidth=2)
ax.set_xlabel("Flipper length (mm, bin centre)")
ax.set_ylabel("Mean body mass (g)")
ax.set_title("Body mass rises with flipper length")
fig.tight_layout()
plt.show()
Line plot with markers showing mean penguin body mass rising steadily with flipper length. Across flipper-length bins centred at 175 up to 225 millimetres, mean body mass climbs from about 3452 grams to about 5545 grams.
Figure 4

La courbe monte de façon monotone — d’environ 3452 g pour les manchots aux plus petites nageoires à environ 5545 g pour les plus grandes — une tendance nette, quasi linéaire, qu’un nuage de points montrerait de façon plus bruitée. Quand votre x est ordonné et que vous voulez la forme du changement plutôt que les points individuels, reliez-les.

Sous-graphiques : plusieurs tracés dans une figure

Les vrais rapports montrent rarement un seul tracé à la fois. plt.subplots(nrows, ncols) renvoie une Figure et une grille d’Axes, et vous dessinez sur chacun par indice. Demandez 2×2 et axes est un tableau 2-D ; l’aplatir vous permet de boucler ou d’adresser les panneaux directement.

import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 2, figsize=(9, 6.5))

# Top-left: scatter by species
for name, group in penguins.groupby("species"):
    axes[0, 0].scatter(group["bill_length_mm"], group["bill_depth_mm"],
                       label=name, color=palette[name], s=18, alpha=0.8)
axes[0, 0].set(xlabel="Bill length (mm)", ylabel="Bill depth (mm)", title="Bill length vs. depth")
axes[0, 0].legend(fontsize=8, title="Species")

# Top-right: histogram of body mass
axes[0, 1].hist(penguins["body_mass_g"].dropna(), bins=25, color=AZURE, edgecolor="white")
axes[0, 1].set(xlabel="Body mass (g)", ylabel="Count", title="Body mass distribution")

# Bottom-left: mean mass per species
mean_mass = penguins.groupby("species")["body_mass_g"].mean()
axes[1, 0].bar(mean_mass.index, mean_mass.values, color=AZURE)
axes[1, 0].set(xlabel="Species", ylabel="Mean mass (g)", title="Mean mass by species")

# Bottom-right: mass vs flipper-length trend
axes[1, 1].plot(centres, trend.values, marker="o", color=AZURE, linewidth=2)
axes[1, 1].set(xlabel="Flipper length (mm)", ylabel="Mean mass (g)", title="Mass vs. flipper length")

fig.suptitle("Penguins at a glance", fontsize=15, fontweight="bold")
fig.tight_layout()
plt.show()
A two-by-two panel of penguin figures: top-left a scatter of bill length versus depth coloured by species, top-right a histogram of body mass showing two humps, bottom-left a bar chart of mean body mass with Gentoo tallest, bottom-right a line of mean body mass rising with flipper length.
Figure 5

Trois choses gagnent leur place ici. axes[0, 0] adresse le panneau en haut à gauche ; ax.set(...) définit plusieurs propriétés en un seul appel au lieu de quatre lignes séparées ; et fig.suptitle ajoute un titre unique au-dessus de toute la figure tandis que chaque Axes garde le sien. tight_layout() compte encore plus avec une grille — c’est ce qui empêche les panneaux de chevaucher les étiquettes de leurs voisins.

Styler une figure isolée

Le bloc rcParams stylise tout ; parfois vous voulez soigner une figure. Chaque réglage de style est une méthode sur l’Axes ou un argument de l’appel de tracé — couleur, transparence (alpha), épaisseur de trait, marqueur, limites d’axes, mise en forme des graduations.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
for name, group in penguins.groupby("species"):
    ax.scatter(group["bill_length_mm"], group["bill_depth_mm"],
               label=name, color=palette[name], s=40, alpha=0.75,
               edgecolor="white", linewidth=0.5)

ax.set_xlabel("Bill length (mm)")
ax.set_ylabel("Bill depth (mm)")
ax.set_title("Penguin bill dimensions")
ax.set_xlim(30, 60)                       # fix the axis range
ax.legend(title="Species", loc="upper left", bbox_to_anchor=(1.02, 1))  # legend outside
fig.tight_layout()
plt.show()
A polished scatter of bill length versus depth for the three penguin species, with larger semi-transparent points, a legend outside the plot area on the right, and x-axis limits from 30 to 60 millimetres.
Figure 6

set_xlim fixe la plage de x pour qu’elle ne se déplace pas quand les données changent ; s et alpha dimensionnent et adoucissent les points afin que les régions denses se lisent clairement ; et bbox_to_anchor=(1.02, 1) fait flotter la légende juste à l’extérieur du tracé pour qu’elle ne couvre jamais les données. De petits ajustements délibérés — pas une réécriture de thème — voilà ce qui sépare un brouillon d’une figure que vous publieriez.

Sauvegarder une figure de qualité publication

Une figure n’est utile qu’une fois sortie du notebook. fig.savefig l’écrit sur le disque ; les arguments décident de la qualité.

import matplotlib.pyplot as plt
import tempfile, os

fig, ax = plt.subplots()
mean_mass = penguins.groupby("species")["body_mass_g"].mean()
ax.bar(mean_mass.index, mean_mass.values, color=AZURE)
ax.set(xlabel="Species", ylabel="Mean body mass (g)", title="Mean body mass by species")
fig.tight_layout()

# In your own work, pass a real filename: fig.savefig("penguins_mass.png", dpi=300, bbox_inches="tight")
out = os.path.join(tempfile.gettempdir(), "penguins_mass.png")
fig.savefig(out, dpi=300, bbox_inches="tight")
print("saved:", os.path.basename(out), "-", round(os.path.getsize(out) / 1024), "KB")
os.remove(out)             # clean up the demo file
plt.close(fig)             # we saved it above; no need to redisplay the same bar chart here
saved: penguins_mass.png - 58 KB

Trois arguments portent tout le poids. dpi=300 fixe la résolution — 300 est le standard d’impression, 150 suffit amplement pour le web. bbox_inches="tight" rogne les marges blanches environnantes pour que la figure ne baigne pas dans la marge. Et l’extension du fichier choisit le format : .png pour un raster prêt pour le web, .pdf ou .svg pour une sortie vectorielle infiniment agrandissable qu’une revue acceptera, .jpg uniquement pour les photographies. En pratique : fig.savefig("figure.pdf", bbox_inches="tight") pour un article, fig.savefig("figure.png", dpi=200, bbox_inches="tight") pour une diapositive.

Quel tracé pour quelle question ?

Choisissez le tracé à partir de la question, pas de l’habitude :

Votre question Le tracé L’appel
Comment deux variables numériques se relient-elles ? Nuage de points ax.scatter(x, y)
Quelle est la distribution d’une variable ? Histogramme ax.hist(x, bins=...)
Comment une valeur se compare-t-elle entre groupes ? Barres ax.bar(labels, values)
Comment quelque chose évolue-t-il le long d’un axe ordonné (temps, dose) ? Courbe ax.plot(x, y)
Plusieurs des précédents, côte à côte ? Sous-graphiques plt.subplots(r, c)

En cas de doute : une relation veut un nuage de points, la forme d’une variable veut un histogramme, une comparaison de groupes veut des barres, et une tendance le long d’un axe ordonné veut une courbe.

Les mêmes tracés en R

Vous préférez R, ou vous travaillez dans les deux langages ? L’équivalent en grammaire des graphiques se trouve dans la série ggplot2 — par exemple Nuage de points en R avec ggplot2 construit le même nuage longueur-vs-profondeur du bec avec geom_point(). Les concepts se transposent directement : un Axes correspond à un objet ggplot, et ax.set_xlabel correspond à labs(x = ...).

Essayez en direct

Les blocs ci-dessus ont été exécutés au moment de la compilation. Modifiez celui-ci et appuyez sur Run pour tracer les manchots vous-même — il s’exécute dans votre navigateur via Pyodide (aucune installation). Le premier Run télécharge matplotlib et pandas une fois (~20 Mo), puis c’est mis en cache et instantané.

🟢 Avec un agent IA

Apportez votre propre CSV — collez un df.head() de celui-ci et demandez à Prova « quel tracé matplotlib répond à ma question, et écris le code ax correspondant ? » Elle choisit entre nuage de points, histogramme, barres ou courbe à partir de ce que vous demandez et vous remet l’appel étiqueté et stylé. Parce que le runtime est juste là, vous l’exécutez et voyez la figure réelle — puis ajustez les bins, la couleur, les limites d’axes — au lieu de faire confiance à un extrait à l’air plausible. The runtime is the judge. Demander à Prova →

Problèmes fréquents

Rien ne s’affiche (ou la même figure apparaît deux fois). Dans un simple script .py, il vous faut plt.show() pour ouvrir la fenêtre ; dans un notebook, une figure s’affiche automatiquement comme dernière expression d’une cellule, donc appeler plt.show() en plus et renvoyer la figure peut la rendre deux fois. Construisez avec l’API OO et terminez la cellule par plt.show() une seule fois — c’est cohérent partout.

ValueError ou des barres vides à cause de valeurs manquantes. ax.hist et consorts s’étouffent sur les NaN. Écartez-les d’abord pour la colonne que vous tracez — penguins["body_mass_g"].dropna() — sinon le tracé produit une erreur ou laisse silencieusement des trous. C’est le « pourquoi ça ne trace pas ? » le plus courant sur des données réelles.

La légende est vide ou absente. ax.legend() n’affiche d’entrées que pour les artistes qui ont reçu un label=. Si vous avez tracé sans label="..." sur chaque série, ajoutez-le ; si la légende couvre vos données, déplacez-la avec loc= ou faites-la flotter à l’extérieur avec bbox_to_anchor.

Questions fréquentes

plt (pyplot) est un module de raccourcis qui agissent sur la figure « courante » — pratique pour un usage ponctuel rapide. ax est un objet Axes que vous tenez explicitement et sur lequel vous appelez des méthodes (ax.plot, ax.set_title). Le style ax (orienté objet) est sans ambiguïté et le seul qui fonctionne proprement dès que vous avez plusieurs panneaux, alors préférez fig, ax = plt.subplots() et dessinez sur ax. La plupart des fonctions plt.xlabel(...) ont une méthode jumelle ax.set_xlabel(...).

Passez figsize=(width, height) en pouces quand vous créez la figure : fig, ax = plt.subplots(figsize=(8, 5)). Pour changer la valeur par défaut de chaque figure, réglez-la une fois avec plt.rcParams["figure.figsize"] = (8, 5). dpi contrôle le nombre de pixels par pouce, donc figsize × dpi est la résolution finale en pixels.

Utilisez fig.savefig("figure.png", dpi=300, bbox_inches="tight"). dpi=300 est le standard d’impression (utilisez 150 pour le web), et bbox_inches="tight" rogne les marges blanches environnantes. Pour une sortie infiniment agrandissable que les revues préfèrent, sauvegardez plutôt un format vectoriel — fig.savefig("figure.pdf") ou .svg — où dpi n’a plus d’importance.

Ce ne sont pas des rivaux : seaborn est construit par-dessus matplotlib. Seaborn vous donne de jolis tracés statistiques (distributions, comparaisons catégorielles, régressions) en une ligne et lit directement un DataFrame, il est donc plus rapide pour l’exploration. Matplotlib est la couche en dessous qui contrôle chaque détail — et vous l’utilisez pour peaufiner une figure seaborn (les fonctions seaborn renvoient des Axes matplotlib). Apprenez d’abord le modèle Figure/Axes de matplotlib, comme ici ; ensuite les raccourcis de seaborn prennent tout leur sens et vous pouvez toujours descendre jusqu’aux réglages de matplotlib quand vous en avez besoin.

Donnez à chaque série un label= quand vous la dessinez, puis appelez ax.legend() : ax.plot(x, y, label="2024") puis ax.legend(title="Year"). Seuls les artistes étiquetés apparaissent. Déplacez-la avec loc="upper left", ou faites-la flotter à l’extérieur du tracé avec ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left") quand elle couvrirait sinon les données.

Testez vos connaissances

Utilisez les données penguins (penguins = pd.read_csv("penguins.csv")) dans la cellule Essayez en direct ci-dessus.

Tâche 1. Construisez une figure 2×1 (deux panneaux empilés verticalement) avec plt.subplots(2, 1) : un histogramme de flipper_length_mm en haut, et un nuage de points de flipper_length_mm (x) contre body_mass_g (y) en dessous. Étiquetez les deux axes sur chaque panneau et appelez fig.tight_layout().

plt.subplots(2, 1) renvoie fig, axesaxes est un tableau 1-D de longueur 2 — adressez les panneaux comme axes[0] et axes[1]. Écartez les NaN avant l’histogramme.

import matplotlib.pyplot as plt
import pandas as pd
penguins = pd.read_csv("penguins.csv")

fig, axes = plt.subplots(2, 1, figsize=(7, 7))

axes[0].hist(penguins["flipper_length_mm"].dropna(), bins=20,
             color="#3a86d4", edgecolor="white")
axes[0].set(xlabel="Flipper length (mm)", ylabel="Count",
            title="Flipper length distribution")

axes[1].scatter(penguins["flipper_length_mm"], penguins["body_mass_g"],
                color="#3a86d4", s=22, alpha=0.7)
axes[1].set(xlabel="Flipper length (mm)", ylabel="Body mass (g)",
            title="Body mass vs. flipper length")

fig.tight_layout()
plt.show()

L’histogramme montre que la longueur de la nageoire est aussi bimodale (les Gentoo, encore), et le nuage de points montre la relation positive et resserrée que la courbe en bins résumait plus tôt.

Tâche 2. Sauvegardez la figure de la Tâche 1 en PNG à 300 dpi avec une boîte englobante serrée.

fig.savefig("penguins_flippers.png", dpi=300, bbox_inches="tight")

dpi=300 donne la résolution d’impression ; bbox_inches="tight" rogne les marges blanches. Changez l’extension en .pdf pour une sortie vectorielle.

Vérification rapide. Vous écrivez plt.subplots(2, 2) et vous voulez le panneau en bas à droite. Quel est son indice ?

axes[1, 1]. plt.subplots(2, 2) renvoie un tableau 2-D d’Axes indexé [row, col], tous deux à base zéro — donc [0, 0] est en haut à gauche et [1, 1] est en bas à droite.

Conclusion

Vous avez maintenant l’essentiel de matplotlib : le modèle Figure/Axes, les quatre tracés qui répondent à la plupart des questions (nuage de points, histogramme, barres, courbe), les sous-graphiques multi-panneaux, un style maison défini une fois avec rcParams, et un export de qualité publication avec savefig. Le motif est toujours le même — fig, ax = plt.subplots(), dessiner sur ax, l’étiqueter, le disposer avec tight_layout, le sauvegarder. Construisez-les sur vos propres données et les gestes se transposent inchangés ; à partir d’ici, seaborn et le .plot() de pandas sont des raccourcis sur ce même moteur.

Leçons connexes

Cette page vous a-t-elle été utile ?

Prouvez que vous savez le faire. Maîtrisez toute la série Visualisation de données en Python — suivez votre parcours, construisez des projets et obtenez un certificat.

Commencer gratuitement →

Passez à Pro — Prova illimité sur vos propres données et un certificat vérifiable qui atteste la compétence.

dès 15 $/mois facturé annuellement

Passer à Pro →

✓ Vous êtes Pro — continuez. The runtime is the judge.

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Matplotlib en Python : figures, axes, tracés, sous-graphiques
    \& savefig},
  date = {2026-07-17},
  url = {https://www.datanovia.com/learn/programming/python-data-visualization/matplotlib-essentials},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Matplotlib en Python : figures, axes, tracés, sous-graphiques & savefig.” 2026. July 17. https://www.datanovia.com/learn/programming/python-data-visualization/matplotlib-essentials.