Animaciones en matplotlib

Matplotlib puede crear animaciones actualizando una figura fotograma a fotograma. La clase FuncAnimation llama a una función en cada fotograma, en la que modificas los elementos del gráfico. El resultado se puede mostrar en un notebook o guardar como GIF o como vídeo.

Animar una línea con FuncAnimation

El flujo de trabajo habitual es: crear la figura y los elementos que quieres animar, escribir una función que los actualice para un fotograma dado y pasarla a FuncAnimation junto con el número de fotogramas. interval establece el tiempo entre fotogramas en milisegundos.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

x = np.linspace(0, 10, 200)

fig, ax = plt.subplots(figsize = (4, 4))
line, = ax.plot(x, np.sin(x))
ax.set_ylim(-1.2, 1.2)

def update(frame):
    line.set_ydata(np.sin(x + frame / 10))
    return line,

ani = FuncAnimation(fig, update, frames = 63, interval = 40)
# plt.show()

Gráfico de líneas animado en matplotlib con FuncAnimation

Línea que crece con el tiempo

En lugar de mover los datos puedes mostrarlos progresivamente, actualizando los valores de X e Y de la línea con set_data.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

x = np.linspace(0, 10, 100)
y = np.random.default_rng(1).normal(size = 100).cumsum()

fig, ax = plt.subplots(figsize = (4, 4))
line, = ax.plot([], [])
ax.set_xlim(0, 10)
ax.set_ylim(y.min() - 1, y.max() + 1)

def update(frame):
    line.set_data(x[:frame], y[:frame])
    return line,

ani = FuncAnimation(fig, update, frames = len(x) + 1, interval = 40)
# plt.show()

Animación de una línea que crece en matplotlib

Gráfico de dispersión animado

Los puntos de un gráfico de dispersión se actualizan con set_offsets, que recibe un array con las coordenadas X e Y.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

rng = np.random.default_rng(2)
points = rng.normal(size = (50, 2))

fig, ax = plt.subplots(figsize = (4, 4))
sc = ax.scatter(points[:, 0], points[:, 1])
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)

def update(frame):
    points[:] = points + rng.normal(0, 0.05, points.shape)
    sc.set_offsets(points)
    return sc,

ani = FuncAnimation(fig, update, frames = 60, interval = 50)
# plt.show()

Gráfico de dispersión animado en matplotlib

Gráfico de barras animado

En los gráficos de barras actualiza la altura de cada barra con set_height.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

rng = np.random.default_rng(3)
data = rng.uniform(1, 10, (30, 5)).cumsum(axis = 0)

fig, ax = plt.subplots(figsize = (4, 4))
bars = ax.bar(["A", "B", "C", "D", "E"], data[0])
ax.set_ylim(0, data.max() * 1.05)

def update(frame):
    for bar, height in zip(bars, data[frame]):
        bar.set_height(height)
    ax.set_title(f"Paso {frame + 1}")
    return bars

ani = FuncAnimation(fig, update, frames = len(data), interval = 100)
# plt.show()

Gráfico de barras animado en matplotlib

Guardar la animación

Guarda la animación con el método save. Los archivos GIF se crean con Pillow, que se instala junto con matplotlib, mientras que los vídeos MP4 necesitan tener FFmpeg instalado en tu sistema.

from matplotlib.animation import PillowWriter, FFMpegWriter

ani.save("animacion.gif", writer = PillowWriter(fps = 25))
ani.save("animacion.mp4", writer = FFMpegWriter(fps = 25))

Animaciones en notebooks de Jupyter

En un notebook de Jupyter la animación no se muestra con plt.show(). En su lugar conviértela a HTML:

from IPython.display import HTML

HTML(ani.to_jshtml())

Guarda una referencia al objeto de la animación (ani = FuncAnimation(...)). Si el objeto se elimina, la animación se detiene. Para aprender a exportar gráficos estáticos consulta cómo guardar gráficos en matplotlib.

Better Data Visualizations

A Guide for Scholars, Researchers, and Wonks

Comprar en Amazon
Storytelling con Datos

Visualización de datos para profesionales

Comprar en Amazon

También te puede interesar