En este artículo, vamos a aprender cómo hacer un gráfico animado de varias líneas usando matplotlib . Animar los gráficos puede hacer que las cosas sean más atractivas y también ayudar a otros a visualizar los datos de manera más adecuada en lugar de gráficos estáticos. Las animaciones tienen aún más sentido cuando trabajamos con proyectos (mercados de valores, detección de anomalías de ECG, pronóstico de tráfico de Internet) que representan los datos de la serie temporal.
La clase matplotlib.animation.FuncAnimation se utiliza para realizar llamadas de animación de forma recursiva. Debe almacenar la Animación creada en una variable que viva mientras la animación deba ejecutarse. De lo contrario, el objeto Animation se recolectará como basura y la animación se detendrá.
Sintaxis: class matplotlib.animation.FuncAnimation(fig, func, frames=Ninguno, init_func=Ninguno, fargs=Ninguno, save_count=Ninguno, *, cache_frame_data=True, **kwargs)
Ejemplo 1:
Para matplotlib hay dos módulos importantes que necesitamos principalmente: pyplot y animation(Funcanimation) . A continuación se muestra un enfoque paso a paso sobre cómo animar líneas en matplotlib. Vamos a hacer nuestro primer ejemplo con 4 parcelas construidas manualmente usando los números aleatorios en un cierto rango.
- Importe todas las bibliotecas necesarias para crear gráficos y animaciones.
Python3
# importing all necessary libraries import random import matplotlib from matplotlib import animation import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation %matplotlib qt
- Ahora haga 4 conjuntos diferentes de y, es decir, y1,y2,y3,y4 que van a compartir con los mismos valores del eje x. Mientras tomamos los valores aleatorios, vamos a dividir cada valor aleatorio porque estos nos ayudarán a obtener diferentes líneas exponenciales.
Python3
# add random points for each line l1 = [random.randint(-20, 4)+(points**1.88)/(random.randint(13, 14)) for points in range(0, 160, 2)] l2 = [random.randint(0, 9)+(points**1.9)/(random.randint(9, 11)) for points in range(0, 160, 2)] l3 = [random.randint(-10, 10)-(points**1.4)/(random.randint(9, 12)) for points in range(0, 160, 2)] l4 = [random.randint(-5, 10)-(points**1.1)/(random.randint(7, 12)) for points in range(0, 160, 2)]
- Ahora use itertools para iterar. Este módulo funciona rápido, es una herramienta eficiente en memoria que se usa sola o en combinación para formar álgebra iteradora. También puede usar for loop para iterar simplemente cree una lista y comience a almacenar las variables de y wrt x.
Python3
from itertools import count myvar = count(0, 3)
- Cree 3 listas vacías adicionales para nuevas líneas (y2, y3 e y4) en total 5 listas vacías cuando incluimos x1 e y1. Dentro de la función de animación, llenaremos esos contenedores en cada paso de iteración. En cada iteración, se crea una animación de un solo cuadro. Además, agregue colores para 4 líneas diferentes.
Python3
# subplots() function you can draw # multiple plots in one figure fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 5)) # set limit for x and y axis axes.set_ylim(-100, 500) axes.set_xlim(0, 250) # style for plotting line plt.style.use("ggplot") # create 5 list to get store element # after every iteration x1, y1, y2, y3, y4 = [], [], [], [], [] myvar = count(0, 3) def animate(i): x1.append(next(myvar)) y1.append((l1[i])) y2.append((l2[i])) y3.append((l3[i])) y4.append((l4[i])) axes.plot(x1, y1, color="red") axes.plot(x1, y2, color="gray") axes.plot(x1, y3, color="blue") axes.plot(x1, y4, color="green") # set ani variable to call the # function recursively anim = FuncAnimation(fig, animate, interval=30)
A continuación el programa completo:
Python3
# importing all necessary libraries from itertools import count import random import matplotlib from matplotlib import animation import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation %matplotlib qt # add random points for each line l1 = [random.randint(-20, 4)+(points**1.88)/(random.randint(13, 14)) for points in range(0, 160, 2)] l2 = [random.randint(0, 9)+(points**1.9)/(random.randint(9, 11)) for points in range(0, 160, 2)] l3 = [random.randint(-10, 10)-(points**1.4)/(random.randint(9, 12)) for points in range(0, 160, 2)] l4 = [random.randint(-5, 10)-(points**1.1)/(random.randint(7, 12)) for points in range(0, 160, 2)] myvar = count(0, 3) # subplots() function you can draw # multiple plots in one figure fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 5)) # set limit for x and y axis axes.set_ylim(-100, 500) axes.set_xlim(0, 250) # style for plotting line plt.style.use("ggplot") # create 5 list to get store element # after every iteration x1, y1, y2, y3, y4 = [], [], [], [], [] myvar = count(0, 3) def animate(i): x1.append(next(myvar)) y1.append((l1[i])) y2.append((l2[i])) y3.append((l3[i])) y4.append((l4[i])) axes.plot(x1, y1, color="red") axes.plot(x1, y2, color="gray") axes.plot(x1, y3, color="blue") axes.plot(x1, y4, color="green") # set ani variable to call the # function recursively anim = FuncAnimation(fig, animate, interval=30)
Producción :
Ejemplo 2:
Aquí hay otro ejemplo para animar varias líneas en matplotlib.
- Importe todas las bibliotecas necesarias.
Python3
# import modules import numpy as np import matplotlib import matplotlib.pyplot as plt import matplotlib.animation as animation
- Cree una línea de actualización de función para obtener un nuevo valor para cada iteración.
Python3
def updateline(num, data, line1, data2, line2): line1.set_data(data[..., :num]) line2.set_data(data2[..., :num]) time_text.set_text("Points: %.0f" % int(num)) return line1, line2 # generating data of 100 elements # each for line 1 x = np.linspace(0, 2*np.pi, 100) y = np.sin(x) data = np.array([x, y]) # generating data of 100 elements # each for line 2 x2 = np.linspace(0, 2*np.pi, 100) y2 = np.cos(x2) data2 = np.array([x2, y2]) # setup the formating for moving files Writer = animation.writers['ffmpeg'] Writer = Writer(fps=10, metadata=dict(artist="Me"), bitrate=-1) fig = plt.figure() ax = fig.add_subplot(111) l, = ax.plot([], [], 'r-', label="Sin") ax2 = ax.twinx() k = ax2.plot([], [], 'b-', label="Cos")[0] ax.legend([l, k], [l.get_label(), k.get_label()], loc=0) ax.set_xlabel("X") # axis 1 ax.set_ylim(-1.5, 1.5) ax.set_xlim(0, 7) # axis 2 ax2.set_ylim(-1.5, 1.5) ax2.set_xlim(0, 7) plt.title('Sin and Cos') time_text = ax.text(0.1, 0.95, "", transform=ax.transAxes, fontsize=15, color='red')
- Guardar archivo mp4 [Por defecto, los archivos se guardan en su directorio actual].
Python3
# set line_animation variable to call # the function recursively line_animation = animation.FuncAnimation( fig, updateline, frames=100, fargs=(data, l, data2, k)) line_animation.save("lines.mp4", writer=Writer)
A continuación el programa completo:
Python3
# import required modules import numpy as np import matplotlib import matplotlib.pyplot as plt import matplotlib.animation as animation def updateline(num, data, line1, data2, line2): line1.set_data(data[..., :num]) line2.set_data(data2[..., :num]) time_text.set_text("Points: %.0f" % int(num)) return line1, line2 # generating data of 100 elements # each for line 1 x = np.linspace(0, 2*np.pi, 100) y = np.sin(x) data = np.array([x, y]) # generating data of 100 elements # each for line 2 x2 = np.linspace(0, 2*np.pi, 100) y2 = np.cos(x2) data2 = np.array([x2, y2]) # setup the formating for moving files Writer = animation.writers['ffmpeg'] Writer = Writer(fps=10, metadata=dict(artist="Me"), bitrate=-1) fig = plt.figure() ax = fig.add_subplot(111) l, = ax.plot([], [], 'r-', label="Sin") ax2 = ax.twinx() k = ax2.plot([], [], 'b-', label="Cos")[0] ax.legend([l, k], [l.get_label(), k.get_label()], loc=0) ax.set_xlabel("X") # axis 1 ax.set_ylim(-1.5, 1.5) ax.set_xlim(0, 7) # axis 2 ax2.set_ylim(-1.5, 1.5) ax2.set_xlim(0, 7) plt.title('Sin and Cos') time_text = ax.text(0.1, 0.95, "", transform=ax.transAxes, fontsize=15, color='red') # set line_animation variable to call # the function recursively line_animation = animation.FuncAnimation( fig, updateline, frames=100, fargs=(data, l, data2, k)) line_animation.save("lines.mp4", writer=Writer)
Producción :