График динамического изменения графика с использованием matplotlib в Jupyter Notebook

У меня есть массив M x N 2D: i-я строка представляет это значение N точек в момент i.

Я хочу визуализировать точки [1 строку массива] в виде графика, в котором значения обновляются после небольшого интервала. Таким образом, график показывает по 1 строке за раз, затем обновляет значения до следующей строки, так далее и т.д.

Я хочу сделать это в ноутбуке jupyter. Поиск ссылочных кодов.

Я пробовал следующие вещи, но не имел успеха:

Ответ 2

Здесь альтернативное, возможно, более простое решение:

%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()

Ответ 3

Я особенно искал хороший ответ для сценария, когда один поток перекачивает данные, и мы хотим, чтобы блокнот Jupyter продолжал обновлять график, ничего не блокируя. Посмотрев около десятка или около того связанных ответов, вот некоторые из выводов:

предосторожность

Не используйте ниже магию, если вы хотите живой график. Обновление графика не работает, если ноутбук использует ниже:

%load_ext autoreload
%autoreload 2

Перед тем, как импортировать matplotlib, вам нужно немного магии в своем блокноте:

%matplotlib notebook

Метод 1: Использование FuncAnimation

Недостатком является то, что обновление графика происходит, даже если ваши данные еще не были обновлены. В следующем примере показан другой поток, обновляющий данные, в то время как график обновления блокнота FuncAnimation через 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()

Способ 2: прямое обновление

Второй способ - обновить график, когда данные поступают из другого потока. Это рискованно, потому что matplotlib не является потокобезопасным, но, похоже, он работает, пока только один поток выполняет обновления.

%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()

Ответ 4

В дополнение к @0aslam0 я использовал код здесь. Я только что изменил функцию анимации, чтобы получить следующую строку в следующий раз. Он рисует анимированную эволюцию (М шагов) всех N точек.

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())

Надеюсь, это будет полезно

Ответ 5

Вот библиотека, которая занимается данными о реальном времени/записи данных в режиме реального времени (джойстик), хотя я не уверен, что она работает с jupyter. Вы можете установить его с помощью обычного pip install joystick.

Трудно сделать рабочее решение без дополнительной информации о ваших данных. Вот вариант:

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()

Этот код создаст график, который автоматически обновляется 5 раз в секунду (freq_up = 5), в то время как новые данные генерируются (произвольно) каждые 0,5 секунды (wait_time = 0,5) и выводятся на график для отображения.

Если вы не хотите, чтобы ось Y t.mygraph.xylim = (0, t.shape[1]-1, 0, 1) вокруг, введите t.mygraph.xylim = (0, t.shape[1]-1, 0, 1).

Ответ 6

Я исследовал это и произвел следующее, в значительной степени самодокументированное:

import matplotlib.pyplot as plt
%matplotlib notebook

print('This text appears above the figures')
fig1 = plt.figure(num='DORMANT')
print('This text appears betweeen the figures')
fig2 = plt.figure()
print('This text appears below the figures')

fig1.canvas.set_window_title('Canvas active title')
fig1.suptitle('Figure title', fontsize=20)

# Create plots inside the figures
ax1 = fig1.add_subplot(111)
ax1.set_xlabel('x label')
ax2 = fig2.add_subplot(111)

# Loop to update figures
end = 40
for i in range(end):
    ax2.cla()  # Clear only 2nd figure axes, figure 1 is ADDITIVE
    ax1.set_title('Axes title')  # Reset as removed by cla()

    ax1.plot(range(i,end), (i,)*(end-i))
    ax2.plot(range(i,end), range(i,end), 'rx')
    fig1.canvas.draw()
    fig2.canvas.draw()

Ответ 7

Я мало знаю о matplotlib или jupyter. Тем не менее, меня интересуют графики. Я просто сделал какой-то поисковик и наткнулся на этот пост. Похоже, вам нужно отобразить график в виде HTML-видео, чтобы увидеть динамический граф.

Я пробовал этот пост. Это ноутбук, если вы хотите попробовать. Обратите внимание, что ядро (python 2) требуется для создания видео. Вы можете прочитать об этом здесь.

Теперь вы хотите отобразить строку графика для строки. Я попробовал это. В этом ноутбуке у меня есть dump_data с 10 строками. Я случайным образом беру один и рисую их и показываю как видео.

Было интересно узнать о юпитере. Надеюсь это поможет.