Audiencia. Personas que ya han visto algo de programación y quieren repasar Python de forma práctica.
Prerrequisitos. NumPy y análisis básico de datos. Requiere matplotlib.
Duración orientativa. 60–90 minutos, incluida la práctica.
Objetivos de aprendizaje
- Construir figuras con la interfaz orientada a objetos de Matplotlib.
- Elegir entre línea, dispersión, barras e histograma.
- Crear subgráficos, etiquetas, leyendas y anotaciones legibles.
- Guardar figuras y aplicar principios básicos de comunicación visual.
Itinerario
- Modelo figura–ejes
- Líneas
- Dispersión
- Barras
- Histogramas
- Subgráficos
- Anotación y guardado
- Práctica
Cómo trabajar: ejecuta las celdas en orden, predice el resultado antes de verlo y modifica los ejemplos. Cada bloque termina con un ejercicio, un punto de partida y una solución posible.
1. Figura y ejes
Matplotlib distingue Figure (lienzo completo) y Axes (zona con coordenadas). La interfaz orientada a objetos —fig, ax = plt.subplots()— escala mejor que depender del estado global. tight_layout o constrained_layout evita solapamientos.
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("seaborn-v0_8-whitegrid")
COLOR_PRINCIPAL = "#3366CC"
COLOR_SECUNDARIO = "#E45756"
rng = np.random.default_rng(2026)
fig, ax = plt.subplots(figsize=(6, 2.8), constrained_layout=True)
ax.text(0.5, 0.5, "Figure contiene uno o más Axes", ha="center", va="center", fontsize=13)
ax.set_axis_off()
plt.show()
2. Gráficos de líneas
Una línea muestra evolución sobre una variable ordenada, normalmente tiempo. Incluye unidades, título informativo y leyenda solo cuando haya varias series.
meses = np.arange(1, 13)
ventas_2025 = np.array([20, 22, 21, 25, 28, 30, 29, 31, 35, 34, 38, 42])
ventas_2026 = ventas_2025 * np.array([1.05, 1.02, 1.08, 1.1, 1.07, 1.12, 1.11, 1.08, 1.13, 1.15, 1.12, 1.1])
fig, ax = plt.subplots(figsize=(7, 3.5), constrained_layout=True)
ax.plot(meses, ventas_2025, marker="o", label="2025")
ax.plot(meses, ventas_2026, marker="o", label="2026")
ax.set(title="Ventas mensuales", xlabel="Mes", ylabel="Miles de euros")
ax.set_xticks(meses)
ax.legend(frameon=False)
plt.show()
3. Dispersión
Un diagrama de dispersión muestra relación entre dos variables numéricas. Color y tamaño pueden codificar dimensiones adicionales, pero conviene no sobrecargar. Una barra de color debe indicar la escala.
horas = rng.uniform(1, 12, 45)
experiencia = rng.integers(0, 6, 45)
puntuacion = 45 + 4 * horas + 2 * experiencia + rng.normal(0, 6, 45)
fig, ax = plt.subplots(figsize=(6.5, 3.8), constrained_layout=True)
puntos = ax.scatter(horas, puntuacion, c=experiencia, s=55, cmap="viridis", alpha=0.8, edgecolor="white")
ax.set(title="Práctica y resultado", xlabel="Horas de práctica", ylabel="Puntuación")
fig.colorbar(puntos, ax=ax, label="Años de experiencia")
plt.show()
4. Barras
Las barras comparan magnitudes por categoría. El eje cuantitativo suele comenzar en cero. Ordenar categorías ayuda a encontrar patrones; las barras horizontales funcionan bien con etiquetas largas.
categorias = np.array(["Documentación", "Práctica", "Vídeos", "Tutoría"])
valoraciones = np.array([8.7, 9.2, 7.4, 8.1])
orden = np.argsort(valoraciones)
fig, ax = plt.subplots(figsize=(6.5, 3.5), constrained_layout=True)
barras = ax.barh(categorias[orden], valoraciones[orden], color=COLOR_PRINCIPAL)
ax.bar_label(barras, fmt="%.1f", padding=3)
ax.set(title="Valoración de recursos", xlabel="Puntuación sobre 10", xlim=(0, 10))
plt.show()
5. Histogramas
Un histograma aproxima la distribución de una variable continua. El número de intervalos cambia la lectura: prueba varios y justifica la elección. Para comparar grupos, considera paneles separados o transparencia moderada.
tiempos = rng.lognormal(mean=2.3, sigma=0.35, size=500)
fig, ax = plt.subplots(figsize=(6.5, 3.5), constrained_layout=True)
ax.hist(tiempos, bins="auto", color=COLOR_PRINCIPAL, alpha=0.8, edgecolor="white")
ax.axvline(np.median(tiempos), color=COLOR_SECUNDARIO, linestyle="--", label=f"Mediana: {np.median(tiempos):.1f}")
ax.set(title="Distribución del tiempo de resolución", xlabel="Minutos", ylabel="Frecuencia")
ax.legend(frameon=False)
plt.show()
6. Subgráficos y escalas compartidas
plt.subplots(filas, columnas) devuelve una cuadrícula de ejes. Comparte escalas con sharex o sharey cuando facilite comparaciones. No metas demasiada información en un solo panel.
x = np.linspace(0, 2 * np.pi, 200)
fig, axes = plt.subplots(1, 2, figsize=(9, 3.2), sharey=True, constrained_layout=True)
axes[0].plot(x, np.sin(x), color=COLOR_PRINCIPAL)
axes[0].set(title="Seno", xlabel="x", ylabel="amplitud")
axes[1].plot(x, np.cos(x), color=COLOR_SECUNDARIO)
axes[1].set(title="Coseno", xlabel="x")
fig.suptitle("Funciones periódicas")
plt.show()
7. Matrices y mapas de calor
imshow representa una matriz con color. Usa un mapa secuencial para magnitudes y uno divergente cuando existe un centro significativo. La barra de color comunica la escala.
correlaciones = np.array([
[1.00, 0.72, -0.18],
[0.72, 1.00, -0.35],
[-0.18, -0.35, 1.00],
])
etiquetas = ["Práctica", "Nota", "Errores"]
fig, ax = plt.subplots(figsize=(4.8, 3.8), constrained_layout=True)
imagen = ax.imshow(correlaciones, cmap="coolwarm", vmin=-1, vmax=1)
ax.set_xticks(range(3), etiquetas, rotation=30, ha="right")
ax.set_yticks(range(3), etiquetas)
for i in range(3):
for j in range(3):
ax.text(j, i, f"{correlaciones[i, j]:.2f}", ha="center", va="center")
fig.colorbar(imagen, ax=ax, label="Correlación")
ax.set_title("Relaciones entre variables")
plt.show()
8. Anotación y guardado
Anota solo puntos que apoyen el mensaje. Al guardar, elige formato: PNG para mapa de bits, SVG/PDF para vector. dpi afecta a formatos raster. Aquí guardamos en memoria para mantener el notebook autocontenido.
from io import BytesIO
x = np.arange(1, 8)
y = np.array([3, 5, 4, 8, 7, 11, 10])
maximo = int(np.argmax(y))
fig, ax = plt.subplots(figsize=(6, 3.2), constrained_layout=True)
ax.plot(x, y, marker="o", color=COLOR_PRINCIPAL)
ax.annotate(
"Máximo",
xy=(x[maximo], y[maximo]),
xytext=(-35, 25),
textcoords="offset points",
arrowprops={"arrowstyle": "->"},
)
ax.set(title="Serie con punto destacado", xlabel="Semana", ylabel="Valor")
buffer_png = BytesIO()
fig.savefig(buffer_png, format="png", dpi=150, bbox_inches="tight")
print(f"PNG generado en memoria: {buffer_png.tell() / 1024:.1f} KiB")
plt.show()
PNG generado en memoria: 37.7 KiB
Principios y errores habituales
- Elige el gráfico según la pregunta, no por decoración.
- Incluye unidades y contexto; evita títulos genéricos.
- No uses un arcoíris ni dependas solo del color para distinguir series.
- Evita ejes truncados en barras, 3D ornamental y leyendas redundantes.
- Reduce tinta innecesaria y destaca una conclusión.
Extensión opcional: explora escalas logarítmicas, fechas, estilos propios y animación. Para gráficos estadísticos de alto nivel, investiga Seaborn.
Práctica · Mini panel de rendimiento
Con las series mensuales dadas, crea una figura con dos paneles:
- línea de ingresos mensuales;
- barras de incidencias mensuales;
- título general, unidades, marcadores y colores accesibles;
- una anotación en el máximo de ingresos.
import numpy as np
import matplotlib.pyplot as plt
meses = np.arange(1, 7)
ingresos = np.array([21, 24, 23, 29, 31, 28])
incidencias = np.array([14, 11, 13, 8, 6, 9])
# TODO: crea `fig, axes` y dibuja los dos paneles.
Ver una solución posible
import numpy as np
import matplotlib.pyplot as plt
meses = np.arange(1, 7)
ingresos = np.array([21, 24, 23, 29, 31, 28])
incidencias = np.array([14, 11, 13, 8, 6, 9])
indice_max = int(np.argmax(ingresos))
fig, axes = plt.subplots(1, 2, figsize=(9.5, 3.5), constrained_layout=True)
axes[0].plot(meses, ingresos, marker="o", color=COLOR_PRINCIPAL)
axes[0].annotate(
"máximo",
xy=(meses[indice_max], ingresos[indice_max]),
xytext=(8, -28),
textcoords="offset points",
arrowprops={"arrowstyle": "->"},
)
axes[0].set(title="Ingresos", xlabel="Mes", ylabel="Miles de euros", xticks=meses)
axes[1].bar(meses, incidencias, color=COLOR_SECUNDARIO)
axes[1].set(title="Incidencias", xlabel="Mes", ylabel="Número", xticks=meses)
fig.suptitle("Rendimiento del primer semestre")
plt.show()
Comprobación rápida
- [ ] Distingo figura y ejes y uso la interfaz orientada a objetos.
- [ ] Sé elegir un gráfico básico según la pregunta.
- [ ] Puedo etiquetar, anotar y guardar una visualización legible.