使用Jupyter Notebook中的matplotlib绘制动态变化的图形

Anu*_*pta 24 python plot graph matplotlib jupyter-notebook

我有一个M x N 2D数组:第i行代表在时间i的N个点的值.

我希望以图形的形式可视化点[数组的1行],其中值在一小段时间后得到更新.因此,图表一次显示1行,然后将值更新为下一行,依此类推.

我想在一个jupyter笔记本中这样做.寻找参考代码.

我尝试了一些事情,但没有成功:

小智 49

这是另一种可能更简单的解决方案:

%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()
Run Code Online (Sandbox Code Playgroud)

  • 图表不会出现在jupyter实验室中.只有一条消息:`JupyterLab中禁用了JavaScript输出 (11认同)
  • 这样可行,但是在完全渲染之前,笔记本中的绘图显得非常小.完成渲染后,它会调整大小以正确调整大小.知道为什么吗? (10认同)

Shi*_*hah 11

我一直在寻找一个很好的解决方案,即一个线程正在抽取数据并且我们希望 Jupyter Notebook 能够在不阻塞任何内容的情况下不断更新图形。在浏览了大约十几个相关答案后,以下是一些发现:

警告

如果您想要实时图表,请不要使用以下魔法。如果笔记本使用以下内容,则图形更新不起作用:

%load_ext autoreload
%autoreload 2
Run Code Online (Sandbox Code Playgroud)

在导入 matplotlib 之前,您需要在笔记本中使用以下魔法:

%matplotlib notebook
Run Code Online (Sandbox Code Playgroud)

方法一:使用 FuncAnimation

这有一个缺点,即使您的数据尚未更新,也会发生图形更新。下面的示例显示了另一个线程更新数据,而 Jupyter notebook 通过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()
Run Code Online (Sandbox Code Playgroud)

方法二:直接更新

第二种方法是在数据从另一个线程到达时更新图。这是有风险的,因为 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()
Run Code Online (Sandbox Code Playgroud)


Ily*_*rov 7

另一个简单的解决方案,基于IPython.display函数displayclear_output. 我在这里找到的。这是代码(基于@graham-s的答案):

from IPython.display import display, clear_output
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline

m = 100
n = 100
matrix = np.random.normal(0, 1, size=(m, n))

fig = plt.figure()
ax = fig.add_subplot(111)

for i in range(m):
    ax.clear()
    ax.plot(matrix[i, :])
    display(fig)
    clear_output(wait=True)
    plt.pause(0.2)
Run Code Online (Sandbox Code Playgroud)

它使用%matplotlib inline而不是notebook,并且不会产生@MasterScrat 提到的小图像。适用于 Jupyter Notebook 和 Jupyter Lab。有时图像会闪烁,这不太好,但可用于快速调查。

如果需要保持不同帧之间的轴范围,请在 后面添加ax.set_xlim/ 。ax.set_ylimax.clear()


Anu*_*pta 6

我创建了一个带有几个例子ipython笔记本.

  • 在这个答案中,最好从这个笔记本中提取有趣的信息. (10认同)
  • 如果您在此处输入代码,那是很好的。因为网站/用户有时可能会意外删除链接 (2认同)

Tom*_*ale 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's 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()
Run Code Online (Sandbox Code Playgroud)


0as*_*am0 -8

我对 matplotlib 或 jupyter 不太了解。然而,图表让我感兴趣。我刚刚做了一些谷歌搜索,发现了这篇文章。似乎您必须将图表呈现为 HTML 视频才能查看动态图表。

我试过那个帖子。是笔记本,如果你想尝试的话。请注意,内核 (python 2) 需要一些时间来构建视频。你可以在这里读更多关于它的内容读更多关于它的内容。

现在您想要逐行显示图表。我试过这个。在那个笔记本中,我有dump_data10 行。我随机选取一个并将它们绘制出来并显示为视频。

了解 jupyter 很有趣。希望这可以帮助。

  • 恕我直言,只是写 *“看看这个外部页面,或者那个”* 是一个非常糟糕的做法。两年后,这些链接将失效,您的答案将毫无用处。 (9认同)