Skip to content

Axe secondaire Matplotlib : twinx vs secondary_yaxis expliqué

Updated on

Un graphique peut avoir besoin de deux échelles (dollars vs unités, °C vs °F). Mal placer la seconde achèverait la lisibilité: ticks décalés, légendes incohérentes, étiquettes coupées. La parade est simple : choisir l’outil double-axe adapté et fournir une conversion claire pour garder les deux échelles honnêtes.

Guide de décision rapide

ApprocheÀ utiliser quandAtoutsPoints de vigilance
twinx / twinyDeux séries indépendantes partagent les positions x (ou y)Rapide, peu de codeFormatage des ticks manuel, aucune synchronisation auto
secondary_yaxis / secondary_xaxisLes séries sont convertibles (p. ex. °C ↔ °F)Aligne les ticks via fonctions directe/inverseConversion précise requise; seulement pour fonctions monotones
Deux subplots partagent un axeComparaison sans superpositionSéparation clairePlus d’espace, légendes par subplot

Recette : twinx pour deux axes y

import matplotlib.pyplot as plt
import numpy as np
 
x = np.arange(1, 13)
sales = np.array([12, 18, 25, 30, 28, 35, 40, 38, 32, 28, 22, 18])
customers = np.array([120, 155, 180, 210, 205, 230, 245, 240, 225, 200, 175, 150])
 
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(x, sales, color="tab:blue", label="Ventes (k$)")
ax.set_xlabel("Mois")
ax.set_ylabel("Ventes (k$)", color="tab:blue")
ax.tick_params(axis="y", labelcolor="tab:blue")
 
ax2 = ax.twinx()
ax2.plot(x, customers, color="tab:orange", label="Clients")
ax2.set_ylabel("Clients", color="tab:orange")
ax2.tick_params(axis="y", labelcolor="tab:orange")
 
lignes = ax.get_lines() + ax2.get_lines()
etiquettes = [line.get_label() for line in lignes]
ax.legend(lignes, etiquettes, loc="upper left")
plt.tight_layout()
plt.show()

Conseils :

  • Couleurs distinctes par axe pour une légende lisible.
  • Combine les lignes des deux axes avant d’appeler legend.
  • tight_layout() ou constrained_layout=True évitent les étiquettes coupées.

Recette : secondary_yaxis avec conversion sûre

import matplotlib.pyplot as plt
import numpy as np
 
temps_c = np.linspace(-20, 40, 200)
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(temps_c, np.sin(temps_c / 10), color="tab:blue", label="Signal vs °C")
ax.set_xlabel("Température (°C)")
ax.set_ylabel("Signal")
 
def c_to_f(c):
    return c * 9/5 + 32
 
def f_to_c(f):
    return (f - 32) * 5/9
 
ax_f = ax.secondary_xaxis("top", functions=(c_to_f, f_to_c))
ax_f.set_xlabel("Température (°F)")
 
ax.legend(loc="lower right")
plt.tight_layout()
plt.show()

Conseils :

  • Fournis toujours la fonction directe et l’inverse pour aligner les ticks.
  • Reste sur des conversions monotones et inversibles.
  • Formate les ticks (ax_f.xaxis.set_major_formatter("{x:.0f}°F")) pour plus de clarté.

Garder les échelles honnêtes

  • Évite le double axe si les séries ne sont pas liées; deux subplots sont souvent plus clairs.
  • Surveille les pentes trompeuses : si une série domine, normalise d’abord.
  • Active la grille seulement sur l’axe principal pour limiter le bruit visuel.

Checklist de dépannage

  • Légendes en double ? Combine les lignes des deux axes puis appelle legend.
  • Étiquettes coupées ? constrained_layout=True ou plt.tight_layout().
  • Couleurs de ticks incohérentes ? Applique tick_params(labelcolor=...) sur chaque axe.