Cuadrículas en Matplotlib
Las cuadrículas (grids), las anotaciones y los ejes gemelos son recursos que transforman un gráfico básico en una visualización informativa y profesional. Añadir líneas de referencia, señalar puntos relevantes con flechas y combinar dos escalas distintas en la misma figura son técnicas que se utilizan constantemente en informes y publicaciones.
Personalización de la cuadrícula
La cuadrícula facilita la lectura de valores al proporcionar líneas de referencia horizontales y verticales. El método grid() acepta parámetros para controlar el eje afectado (axis), el nivel de detalle (which: 'major', 'minor' o 'both') y el aspecto visual (linestyle, linewidth, alpha, color):
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# Cuadrícula mínima
axes[0].plot(x, np.sin(x))
axes[0].grid(True)
axes[0].set_title('grid(True) — por defecto')
# Cuadrícula personalizada
axes[1].plot(x, np.sin(x))
axes[1].grid(True, which='both', linestyle='--', linewidth=0.8, alpha=0.5, color='gray')
axes[1].set_title('Cuadrícula personalizada')
# Cuadrícula solo en un eje
axes[2].bar(['A', 'B', 'C', 'D'], [4, 7, 3, 9], color='coral')
axes[2].grid(True, axis='y', linestyle=':', alpha=0.6)
axes[2].set_title("grid(axis='y') — solo horizontal")
plt.tight_layout()
plt.show()
En gráficos de barras es habitual activar la cuadrícula solo en el eje Y (
axis='y') para no interferir con las barras verticales.
Texto y anotaciones
ax.text(): texto libre en el gráfico
El método ax.text() coloca texto en una posición concreta del gráfico. Las coordenadas pueden expresarse en unidades de datos (los valores reales de los ejes) o en coordenadas relativas del eje (de 0 a 1) usando el parámetro transform=ax.transAxes. Esta segunda opción es útil para colocar texto en una esquina independientemente del rango de datos:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 200)
y = np.sin(x) * np.exp(-x / 8)
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x, y, 'royalblue', linewidth=2)
ax.axhline(0, color='black', linewidth=0.7)
# Texto en coordenadas de datos
ax.text(2, 0.7, 'Máximo inicial', fontsize=11, color='darkgreen',
ha='center')
# Texto en coordenadas del eje (0-1 relativo)
ax.text(0.98, 0.95, 'Onda amortiguada',
transform=ax.transAxes, # coordenadas del eje
ha='right', va='top', fontsize=10,
bbox=dict(facecolor='lightyellow', edgecolor='gray', alpha=0.8))
ax.set_title('Texto libre con ax.text()')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Anotaciones con flecha con annotate()
La función annotate() es más completa que text() porque permite dibujar una flecha que conecta el texto con el punto del gráfico que se quiere señalar. Los dos parámetros clave son xy (el punto de destino) y xytext (la posición del texto). El diccionario arrowprops controla el estilo de la flecha: forma, color, curvatura y grosor:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 4 * np.pi, 300)
y = np.sin(x)
# Puntos especiales
idx_max = np.argmax(y[:100])
idx_min = np.argmin(y[100:200]) + 100
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(x, y, 'royalblue', linewidth=2)
ax.set_ylim(-1.5, 1.7)
# Anotación básica
ax.annotate('Máximo local',
xy=(x[idx_max], y[idx_max]), # punto a señalar
xytext=(x[idx_max] - 1, 1.4), # posición del texto
arrowprops=dict(arrowstyle='->', color='black', lw=1.5),
fontsize=10, ha='center')
# Anotación con flecha curvada
ax.annotate('Mínimo local',
xy=(x[idx_min], y[idx_min]),
xytext=(x[idx_min] + 1.5, -1.4),
arrowprops=dict(
arrowstyle='fancy',
color='red',
connectionstyle='arc3,rad=0.3'
),
fontsize=10, color='red')
# Anotación con caja de texto
ax.annotate('Cruce por cero',
xy=(np.pi, 0),
xytext=(np.pi + 1, 0.6),
arrowprops=dict(arrowstyle='->', color='green'),
fontsize=9,
bbox=dict(boxstyle='round,pad=0.3', facecolor='lightgreen', alpha=0.7))
ax.grid(True, alpha=0.3)
ax.set_title('Anotaciones con annotate() — diferentes estilos de flecha')
plt.tight_layout()
plt.show()
Los estilos de flecha más útiles son
'->'(flecha recta),'fancy'(flecha decorativa) y'wedge'(forma de cuña). El parámetroconnectionstylecontrola la curvatura, por ejemplo'arc3,rad=0.3'produce una flecha curva.
Ejes gemelos (twin axes)
Eje Y secundario con twinx()
En muchas situaciones se necesitan representar dos magnitudes con escalas muy diferentes en el mismo gráfico. Por ejemplo, temperatura y precipitación, o ventas y beneficio. El método twinx() crea un segundo eje Y que comparte el mismo eje X pero mantiene su propia escala independiente:
import matplotlib.pyplot as plt
import numpy as np
meses = np.arange(1, 13)
temperatura = [7.2, 8.5, 12.1, 15.8, 19.3, 23.7, 26.4, 26.1, 21.9, 16.4, 11.2, 7.8]
precipitacion = [55, 42, 38, 35, 28, 12, 5, 8, 22, 48, 60, 68]
fig, ax1 = plt.subplots(figsize=(11, 6))
# Eje principal: temperatura (línea roja)
color_temp = 'tomato'
ax1.plot(meses, temperatura, 'o-', color=color_temp, linewidth=2.5,
markersize=6, label='Temperatura (°C)')
ax1.set_xlabel('Mes')
ax1.set_ylabel('Temperatura (°C)', color=color_temp, fontsize=12)
ax1.tick_params(axis='y', labelcolor=color_temp)
ax1.set_xticks(meses)
ax1.set_xticklabels(['E','F','M','A','M','J','J','A','S','O','N','D'])
# Eje secundario: precipitación (barras azules)
ax2 = ax1.twinx()
color_prec = 'steelblue'
ax2.bar(meses, precipitacion, alpha=0.4, color=color_prec, label='Precipitación (mm)')
ax2.set_ylabel('Precipitación (mm)', color=color_prec, fontsize=12)
ax2.tick_params(axis='y', labelcolor=color_prec)
# Leyenda combinada de ambos ejes
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left', framealpha=0.9)
ax1.set_title('Temperatura y precipitación anual (Twin axes)', fontsize=13)
ax1.grid(True, linestyle='--', alpha=0.3)
plt.tight_layout()
plt.show()
Al combinar dos ejes Y, es importante colorear cada eje y su etiqueta con el mismo color que la serie correspondiente. Esto ayuda al lector a identificar de un vistazo qué escala pertenece a cada serie.
Escalas logarítmicas
Las escalas logarítmicas son imprescindibles cuando los datos abarcan varios órdenes de magnitud. Matplotlib ofrece set_yscale('log'), set_xscale('log') y la función combinada loglog(). La escala 'symlog' es una alternativa que permite valores negativos y cero, algo que la escala logarítmica estándar no admite.
import matplotlib.pyplot as plt
import numpy as np
x = np.logspace(0, 5, 200)
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# Escala lineal
axes[0].plot(x, x**2, 'royalblue', linewidth=2)
axes[0].set_title('Escala lineal')
axes[0].set_xlabel('x')
axes[0].set_ylabel('x²')
axes[0].grid(True, alpha=0.3)
# Escala log en Y
axes[1].plot(x, x**2, 'coral', linewidth=2)
axes[1].set_yscale('log')
axes[1].set_title('Escala log en Y (semilogy)')
axes[1].set_xlabel('x')
axes[1].grid(True, which='both', alpha=0.3)
# Escala log en ambos ejes (loglog)
axes[2].plot(x, x**2, 'seagreen', linewidth=2)
axes[2].set_xscale('log')
axes[2].set_yscale('log')
axes[2].set_title('Escala log-log')
axes[2].set_xlabel('x (log)')
axes[2].set_ylabel('x² (log)')
axes[2].grid(True, which='both', linestyle=':', alpha=0.4)
plt.tight_layout()
plt.show()
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Matplotlib es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Matplotlib
Explora más contenido relacionado con Matplotlib y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Personalizar la cuadrícula con grid() y sus parámetros. Añadir texto libre con ax.text() en coordenadas de datos o del eje. Crear anotaciones con flecha con annotate() y personalizar arrowprops. Añadir un eje Y secundario con twinx() para dos escalas distintas. Usar escalas logarítmicas con set_xscale('log') y ax.loglog().