python - tiempo - Trazar un gráfico que cambia dinámicamente usando matplotlib en Jupyter Notebook
python graficos 2d (6)
Además de @ 0aslam0 usé el código de here . Acabo de cambiar la función de animación para obtener la siguiente fila cada vez que lo haga. Dibuja una evolución animada (M pasos) de todos los N puntos.
from IPython.display import HTML
import numpy as np
from matplotlib import animation
N = 5
M = 100
points_evo_array = np.random.rand(M,N)
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, M), ylim=(0, np.max(points_evo_array)))
lines = []
lines = [ax.plot([], [])[0] for _ in range(N)]
def init():
for line in lines:
line.set_data([], [])
return lines
def animate(i):
for j,line in enumerate(lines):
line.set_data(range(i), [points_evo_array[:i,j]])
return lines
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate,np.arange(1, M), init_func=init, interval=10, blit=True)
HTML(anim.to_html5_video())
Espero que sea de utilidad.
Tengo una matriz M x N 2D: la fila representa ese valor de N puntos en el momento i.
Quiero visualizar los puntos [1 fila de la matriz] en forma de gráfico donde los valores se actualizan después de un pequeño intervalo. Por lo tanto, el gráfico muestra 1 fila a la vez, luego actualiza los valores a la siguiente fila, y así sucesivamente.
Quiero hacer esto en un cuaderno de jupyter. Buscando códigos de referencia.
Intenté seguir las cosas pero no tuve éxito:
Aquí hay una alternativa, posiblemente una solución más simple:
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
m = 100
n = 100
matrix = np.random.normal(0,1,m*n).reshape(m,n)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.ion()
fig.show()
fig.canvas.draw()
for i in range(0,100):
ax.clear()
ax.plot(matrix[i,:])
fig.canvas.draw()
Aquí hay una biblioteca que se ocupa de los datos de trazado / registro en tiempo real ( joystick ), aunque no estoy seguro de que esté funcionando con jupyter. Puedes instalarlo usando el pip install joystick
habitual para pip install joystick
.
Es difícil hacer una solución de trabajo sin más detalles sobre sus datos. Aquí hay una opción:
import joystick as jk
import numpy as np
class test(jk.Joystick):
# initialize the infinite loop decorator
_infinite_loop = jk.deco_infinite_loop()
def _init(self, *args, **kwargs):
"""
Function called at initialization, see the docs
"""
# INIT DATA HERE
self.shape = (10, 4) # M, N
self.data = np.random.random(self.shape)
self.xaxis = range(self.shape[1])
############
# create a graph frame
self.mygraph = self.add_frame(
jk.Graph(name="TheName", size=(500, 500), pos=(50, 50),
fmt="go-", xnpts=self.shape[1], freq_up=5, bgcol="w",
xylim=(0, self.shape[1]-1, None, None)))
@_infinite_loop(wait_time=0.5)
def _generate_fake_data(self): # function looped every 0.5 second
"""
Loop starting with the simulation start, getting data and
pushing it to the graph every 0.5 seconds
"""
# NEW (RANDOM) DATA
new_data = np.random.random(self.shape[1])
# concatenate data
self.data = np.vstack((self.data, new_data))
# push new data to the graph
self.mygraph.set_xydata(self.xaxis, self.data[-1])
t = test()
t.start()
t.stop()
t.exit()
Este código creará un gráfico que se actualiza automáticamente 5 veces por segundo (freq_up = 5), mientras que los nuevos datos se generan (aleatoriamente) cada 0.5 segundos (wait_time = 0.5) y se envían al gráfico para su visualización.
Si no desea que el eje Y se t.mygraph.xylim = (0, t.shape[1]-1, 0, 1)
, escriba t.mygraph.xylim = (0, t.shape[1]-1, 0, 1)
.
Estuve buscando particularmente una buena respuesta para el escenario en el que un subproceso está bombeando datos y queremos que la notebook Jupyter siga actualizando el gráfico sin bloquear nada. Después de revisar una docena de respuestas relacionadas, aquí están algunos de los hallazgos:
Precaución
No uses la magia de abajo si quieres un gráfico en vivo. La actualización del gráfico no funciona si el cuaderno lo usa a continuación:
%load_ext autoreload
%autoreload 2
Necesitas la magia de abajo en tu cuaderno antes de importar matplotlib:
%matplotlib notebook
Método 1: Uso de FuncAnimation
Esto tiene la desventaja de que la actualización del gráfico se produce incluso si sus datos aún no se han actualizado. El siguiente ejemplo muestra otros datos de actualización de subprocesos mientras el cuaderno de Jupyter actualiza el gráfico a través de FuncAnimation
.
%matplotlib notebook
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from random import randrange
from threading import Thread
import time
class LiveGraph:
def __init__(self):
self.x_data, self.y_data = [], []
self.figure = plt.figure()
self.line, = plt.plot(self.x_data, self.y_data)
self.animation = FuncAnimation(self.figure, self.update, interval=1000)
self.th = Thread(target=self.thread_f, daemon=True)
self.th.start()
def update(self, frame):
self.line.set_data(self.x_data, self.y_data)
self.figure.gca().relim()
self.figure.gca().autoscale_view()
return self.line,
def show(self):
plt.show()
def thread_f(self):
x = 0
while True:
self.x_data.append(x)
x += 1
self.y_data.append(randrange(0, 100))
time.sleep(1)
g = LiveGraph()
g.show()
Método 2: Actualización directa
El segundo método es actualizar el gráfico a medida que los datos llegan de otro hilo . Esto es arriesgado porque matplotlib no es seguro para subprocesos pero parece funcionar siempre y cuando solo haya un subproceso haciendo actualizaciones.
%matplotlib notebook
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from random import randrange
from threading import Thread
import time
class LiveGraph:
def __init__(self):
self.x_data, self.y_data = [], []
self.figure = plt.figure()
self.line, = plt.plot(self.x_data, self.y_data)
self.th = Thread(target=self.thread_f, daemon=True)
self.th.start()
def update_graph(self):
self.line.set_data(self.x_data, self.y_data)
self.figure.gca().relim()
self.figure.gca().autoscale_view()
def show(self):
plt.show()
def thread_f(self):
x = 0
while True:
self.x_data.append(x)
x += 1
self.y_data.append(randrange(0, 100))
self.update_graph()
time.sleep(1)
from live_graph import LiveGraph
g = LiveGraph()
g.show()
No sé mucho sobre matplotlib o jupyter. Sin embargo, los gráficos me interesan. Acabo de hacer un poco de google y me encontré con este post . Parece que tienes que representar el gráfico como un video HTML para ver un gráfico dinámico.
Probé ese post. This es el cuaderno, si quieres intentarlo. Tenga en cuenta que el núcleo (python 2) tarda algún tiempo en crear el video. Puedes leer más sobre esto here .
Ahora desea mostrar un gráfico fila a fila. Intenté this . En ese cuaderno, tengo un dump_data
con 10 filas. Tomo uno al azar y los grabo y los muestro como video.
Fue interesante aprender sobre el jupyter. Espero que esto ayude.