Skip to content

Eje secundario en Matplotlib: twinx vs secondary_yaxis explicado

Updated on

Cuando un gráfico necesita dos escalas (dólares vs unidades, °C vs °F) y la segunda se aplica mal, los lectores interpretan mal la tendencia. Ticks desalineados, leyendas incoherentes y etiquetas cortadas son trampas comunes. La solución es directa: elegir la herramienta de doble eje correcta y aplicar una conversión clara para que ambas escalas sigan siendo fieles.

Guía rápida de decisión

EnfoqueÚsalo cuandoProsPrecauciones
twinx / twinyDos series independientes comparten posiciones en x (o y)Rápido, poco códigoFormato de ticks manual; sin sincronización automática
secondary_yaxis / secondary_xaxisLas series son convertibles (p. ej., °C ↔ °F)Alineación de ticks garantizada con funciones directa/inversaRequiere conversiones precisas; solo para transformaciones monótonas
Dos subplots con ejes compartidosSe quiere comparar sin superponerSeparación claraRequiere más espacio; leyendas por subplot

Receta: twinx para dos escalas 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="Ventas (k$)")
ax.set_xlabel("Mes")
ax.set_ylabel("Ventas (k$)", color="tab:blue")
ax.tick_params(axis="y", labelcolor="tab:blue")
 
ax2 = ax.twinx()
ax2.plot(x, customers, color="tab:orange", label="Clientes")
ax2.set_ylabel("Clientes", color="tab:orange")
ax2.tick_params(axis="y", labelcolor="tab:orange")
 
lineas = ax.get_lines() + ax2.get_lines()
etiquetas = [line.get_label() for line in lineas]
ax.legend(lineas, etiquetas, loc="upper left")
plt.tight_layout()
plt.show()

Consejos:

  • Colores distintos por eje para evitar confusión en la leyenda.
  • Combina las líneas de ambos ejes antes de llamar a legend.
  • Usa tight_layout() o constrained_layout=True para que las etiquetas no se recorten.

Receta: secondary_yaxis con conversiones seguras

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="Señal vs °C")
ax.set_xlabel("Temperatura (°C)")
ax.set_ylabel("Señal")
 
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("Temperatura (°F)")
 
ax.legend(loc="lower right")
plt.tight_layout()
plt.show()

Consejos:

  • Define siempre funciones directa e inversa para mantener los ticks alineados.
  • Usa solo conversiones monótonas e invertibles.
  • Formatea los ticks (ax_f.xaxis.set_major_formatter("{x:.0f}°F")) para mayor claridad.

Mantén las escalas honestas

  • Evita doble eje si las series no están relacionadas; dos subplots suelen ser más claros.
  • Revisa pendientes engañosas: si una serie domina, normaliza antes.
  • Activa la rejilla solo en la primara axis para reducir ruido visual.

Lista rápida de problemas

  • ¿Leyendas duplicadas? Combina líneas de ambos ejes y luego llama a legend.
  • ¿Etiquetas cortadas? Usa constrained_layout=True o plt.tight_layout().
  • ¿Colores de ticks inconsistentes? Aplica tick_params(labelcolor=...) en ambos ejes.