Matplotlib Subplots : Créer des Figures Multipanneaux avec plt.subplots()
Updated on
Les figures à panneau unique suffisent rarement pour une analyse réelle. Vous devez comparer des distributions côte à côte, montrer un nuage de points à côté de ses résidus, ou présenter quatre métriques dans une mise en page de tableau de bord. Sans subplots, vous créeriez des figures séparées qui perdent leur relation visuelle lorsqu'elles sont présentées ensemble.
La fonction plt.subplots() de Matplotlib crée des figures multipanneaux avec des axes partagés, un dimensionnement cohérent et des mises en page flexibles. Ce guide couvre tout, des grilles basiques aux mises en page asymétriques avancées.
Subplots Basiques
Ligne Unique
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
axes[0].plot(x, np.sin(x))
axes[0].set_title('Sinus')
axes[1].plot(x, np.cos(x), color='orange')
axes[1].set_title('Cosinus')
axes[2].plot(x, np.tan(x), color='green')
axes[2].set_ylim(-5, 5)
axes[2].set_title('Tangente')
plt.tight_layout()
plt.show()Disposition en Grille
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
x = np.linspace(0, 10, 100)
axes[0, 0].plot(x, x, 'b-')
axes[0, 0].set_title('Linéaire')
axes[0, 1].plot(x, x**2, 'r-')
axes[0, 1].set_title('Quadratique')
axes[1, 0].plot(x, np.sqrt(x), 'g-')
axes[1, 0].set_title('Racine Carrée')
axes[1, 1].plot(x, np.log(x + 1), 'm-')
axes[1, 1].set_title('Logarithmique')
plt.tight_layout()
plt.show()Axes Partagés
Le partage des axes assure des échelles cohérentes pour la comparaison :
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data1 = np.random.normal(0, 1, 1000)
data2 = np.random.normal(2, 1.5, 1000)
# Partager l'axe X
fig, axes = plt.subplots(2, 1, figsize=(8, 6), sharex=True)
axes[0].hist(data1, bins=30, color='steelblue', alpha=0.7)
axes[0].set_ylabel('Nombre')
axes[0].set_title('Distribution A')
axes[1].hist(data2, bins=30, color='coral', alpha=0.7)
axes[1].set_ylabel('Nombre')
axes[1].set_xlabel('Valeur')
axes[1].set_title('Distribution B')
plt.tight_layout()
plt.show()import matplotlib.pyplot as plt
import numpy as np
# Partager les axes X et Y
fig, axes = plt.subplots(2, 3, figsize=(12, 8), sharex=True, sharey=True)
for i, ax in enumerate(axes.flat):
data = np.random.randn(100)
ax.hist(data, bins=20, color=f'C{i}', alpha=0.7)
ax.set_title(f'Échantillon {i+1}')
plt.tight_layout()
plt.show()Contrôle de l'Espacement et de la Mise en Page
tight_layout()
Ajuste automatiquement l'espacement pour éviter les chevauchements :
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
# ... ajouter des graphiques ...
plt.tight_layout() # Auto-correction de l'espacement
plt.show()subplots_adjust()
Contrôle manuel de l'espacement :
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
plt.subplots_adjust(
left=0.1, # Marge gauche
right=0.95, # Marge droite
top=0.92, # Marge supérieure
bottom=0.08, # Marge inférieure
wspace=0.3, # Espace horizontal entre subplots
hspace=0.4, # Espace vertical entre subplots
)
plt.show()Ajouter un Super Titre
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
fig.suptitle('Fonctions Trigonométriques', fontsize=16, fontweight='bold')
x = np.linspace(0, 2 * np.pi, 100)
for ax, func, name in zip(axes, [np.sin, np.cos, np.tan], ['sin', 'cos', 'tan']):
ax.plot(x, func(x))
ax.set_title(name)
plt.tight_layout()
plt.show()GridSpec pour des Mises en Page Asymétriques
Lorsque vous avez besoin de panneaux de tailles différentes, utilisez GridSpec :
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
fig = plt.figure(figsize=(12, 8))
gs = gridspec.GridSpec(2, 3, figure=fig)
# Grand panneau gauche (s'étend sur 2 lignes)
ax1 = fig.add_subplot(gs[:, 0])
ax1.plot(np.random.randn(100).cumsum())
ax1.set_title('Série Temporelle (2 lignes)')
# Panneaux supérieurs droits
ax2 = fig.add_subplot(gs[0, 1])
ax2.bar(['A', 'B', 'C'], [3, 7, 5])
ax2.set_title('Diagramme en Barres')
ax3 = fig.add_subplot(gs[0, 2])
ax3.scatter(np.random.randn(50), np.random.randn(50))
ax3.set_title('Nuage de Points')
# Panneau inférieur large (s'étend sur 2 colonnes)
ax4 = fig.add_subplot(gs[1, 1:])
ax4.hist(np.random.randn(500), bins=30, color='coral')
ax4.set_title('Histogramme (2 colonnes)')
plt.tight_layout()
plt.show()subplot2grid pour une Mise en Page Positionnelle
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(12, 8))
# (lignes, cols), (ligne_début, col_début), rowspan, colspan
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=2)
ax2 = plt.subplot2grid((3, 3), (0, 2), rowspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0))
ax4 = plt.subplot2grid((3, 3), (1, 1))
ax5 = plt.subplot2grid((3, 3), (2, 0), colspan=3)
ax1.set_title('Haut Large')
ax2.set_title('Droite Haut')
ax3.set_title('Milieu Gauche')
ax4.set_title('Milieu Centre')
ax5.set_title('Bas Pleine Largeur')
plt.tight_layout()
plt.show()Itérer sur les Subplots
import matplotlib.pyplot as plt
import numpy as np
# Aplatir le tableau axes pour une itération facile
fig, axes = plt.subplots(2, 3, figsize=(12, 8))
datasets = [np.random.randn(100) for _ in range(6)]
colors = ['#e74c3c', '#3498db', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c']
for ax, data, color, i in zip(axes.flat, datasets, colors, range(6)):
ax.hist(data, bins=20, color=color, alpha=0.7)
ax.set_title(f'Jeu de Données {i+1}')
ax.set_xlabel('Valeur')
ax.set_ylabel('Nombre')
plt.tight_layout()
plt.show()Supprimer les Subplots Vides
Lorsque vous avez moins de graphiques que de positions dans la grille :
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(2, 3, figsize=(12, 8))
data_count = 5 # Seulement 5 jeux de données pour 6 emplacements
for i, ax in enumerate(axes.flat):
if i < data_count:
ax.plot(np.random.randn(50).cumsum())
ax.set_title(f'Graphique {i+1}')
else:
ax.set_visible(False) # Masquer le subplot vide
plt.tight_layout()
plt.show()Exploration Interactive Multipanneau
Pour une exploration visuelle rapide où vous souhaitez comparer différentes vues du même jeu de données de manière interactive, PyGWalker (opens in a new tab) vous permet de créer des tableaux de bord en glissant-déposant des colonnes dans Jupyter -- sans code de subplot nécessaire :
import pandas as pd
import pygwalker as pyg
df = pd.read_csv('your_data.csv')
walker = pyg.walk(df)FAQ
Comment créer des subplots dans Matplotlib ?
Utilisez fig, axes = plt.subplots(lignes, colonnes) pour créer une figure avec une grille de subplots. Accédez aux axes individuels avec axes[ligne, colonne] pour les grilles ou axes[i] pour les lignes/colonnes uniques. Appelez toujours plt.tight_layout() à la fin pour éviter les chevauchements d'étiquettes.
Comment partager des axes entre subplots ?
Passez sharex=True ou sharey=True à plt.subplots(). Par exemple, fig, axes = plt.subplots(2, 1, sharex=True) fait partager la même échelle de l'axe x aux deux subplots. C'est utile pour comparer des distributions ou des séries temporelles.
Comment créer des subplots de tailles différentes ?
Utilisez matplotlib.gridspec.GridSpec pour des mises en page asymétriques. Créez une grille et utilisez la notation de tranche pour couvrir plusieurs cellules : ax = fig.add_subplot(gs[0, :2]) crée un subplot couvrant les deux premières colonnes de la première ligne.
Comment ajuster l'espacement entre les subplots ?
Appelez plt.tight_layout() pour un espacement automatique. Pour un contrôle manuel, utilisez plt.subplots_adjust(wspace=0.3, hspace=0.4) où wspace est l'espacement horizontal et hspace est l'espacement vertical.
Comment ajouter un titre au-dessus de tous les subplots ?
Utilisez fig.suptitle('Mon Titre', fontsize=16) pour ajouter un super-titre au-dessus de tous les subplots. Vous devrez peut-être ajuster la marge supérieure avec plt.subplots_adjust(top=0.92) ou appeler plt.tight_layout() pour éviter les chevauchements.
Conclusion
Le plt.subplots() de Matplotlib est la base des figures multipanneaux. Utilisez-le avec (lignes, colonnes) pour les grilles régulières, sharex/sharey pour des échelles cohérentes, tight_layout() pour l'espacement automatique, et GridSpec pour les mises en page asymétriques. Pour une itération rapide, aplatissez le tableau axes avec axes.flat et parcourez-le. Ces modèles couvrent la grande majorité des besoins de visualisation multipanneau.