在 Jupyter/iPython 中动态更新绘图的当前正确方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34486642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 15:04:20  来源:igfitidea点击:

What is the currently correct way to dynamically update plots in Jupyter/iPython?

pythonmatplotlibjupyterjupyter-notebook

提问by Nathaniel

In the answers to how to dynamically update a plot in a loop in ipython notebook (within one cell), an example is given of how to dynamically update a plot inside a Jupyter notebook within a Python loop. However, this works by destroying and re-creating the plot on every iteration, and a comment in one of the threads notes that this situation can be improved by using the new-ish %matplotlib nbaggmagic, which provides an interactive figure embedded in the notebook, rather than a static image.

如何在 ipython notebook 中动态更新循环中的绘图(在一个单元格内)的答案中,给出了如何在 Python 循环中动态更新 Jupyter notebook 中的绘图的示例。然而,这是通过在每次迭代中破坏和重新创建情节来实现的,并且其中一个线程中的评论指出这种情况可以通过使用 new-ish%matplotlib nbagg魔法来改善,它提供了一个嵌入在笔记本中的交互式图形,而不是比静态图像。

However, this wonderful new nbaggfeature seems to be completely undocumented as far as I can tell, and I'm unable to find an example of how to use it to dynamically update a plot. Thus my question is, how does one efficiently update an existing plot in a Jupyter/Python notebook, using the nbagg backend?Since dynamically updating plots in matplotlib is a tricky issue in general, a simple working example would be an enormous help. A pointer to any documentation on the topic would also be extremely helpful.

但是,nbagg据我所知,这个美妙的新功能似乎完全没有记录,而且我无法找到如何使用它来动态更新绘图的示例。因此,我的问题是,如何使用 nbagg 后端有效地更新 Jupyter/Python 笔记本中的现有绘图?由于在 matplotlib 中动态更新图通常是一个棘手的问题,一个简单的工作示例将是一个巨大的帮助。指向有关该主题的任何文档的指针也将非常有帮助。

To be clear what I'm asking for: what I want to do is to run some simulation code for a few iterations, then draw a plot of its current state, then run it for a few more iterations, then update the plot to reflect the current state, and so on. So the idea is to draw a plot and then, without any interaction from the user, update the data in the plot without destroying and re-creating the whole thing.

明确我的要求:我想要做的是运行一些模拟代码进行几次迭代,然后绘制其当前状态的图,然后再运行几次迭代,然后更新图以反映当前状态,等等。所以我们的想法是绘制一个图,然后在没有用户任何交互的情况下更新图中的数据,而不会破坏和重新创建整个事物。

Here is some slightly modified code from the answer to the linked question above, which achieves this by re-drawing the whole figure every time. I want to achieve the same result, but more efficiently using nbagg.

这是上面链接问题的答案中的一些稍微修改的代码,它通过每次重新绘制整个图形来实现。我想达到相同的结果,但更有效地使用nbagg.

%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
    pl.clf()
    pl.plot(pl.randn(100))
    display.display(pl.gcf())
    display.clear_output(wait=True)
    time.sleep(1.0)

采纳答案by pneumatics

Here is an example that updates a plot in a loop. It updates the data in the figure and does not redraw the whole figure every time. It does block execution, though if you're interested in running a finite set of simulations and saving the results somewhere, it may not be a problem for you.

这是一个在循环中更新绘图的示例。它更新图中的数据,并不会每次都重新绘制整个图形。它确实会阻止执行,但如果您有兴趣运行一组有限的模拟并将结果保存在某处,这对您来说可能不是问题。

%matplotlib notebook

import numpy as np
import matplotlib.pyplot as plt
import time

def pltsin(ax, colors=['b']):
    x = np.linspace(0,1,100)
    if ax.lines:
        for line in ax.lines:
            line.set_xdata(x)
            y = np.random.random(size=(100,1))
            line.set_ydata(y)
    else:
        for color in colors:
            y = np.random.random(size=(100,1))
            ax.plot(x, y, color)
    fig.canvas.draw()

fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)

I put this up on nbviewer here.

我把这个放在 nbviewer 上。

There is an IPython Widget version of nbaggthat is currently a work in progress at the Matplotlib repository. When that is available, that will probably be the best way to use nbagg.

有一个IPython Widget 版本nbagg目前正在 Matplotlib 存储库中进行中。当它可用时,这可能是使用nbagg.

EDIT: updated to show multiple plots

编辑:更新以显示多个图

回答by Ziofil

I'm using jupyter-lab and this works for me (adapt it to your case):

我正在使用 jupyter-lab,这对我有用(根据您的情况进行调整):

from IPython.display import clear_output
from matplotlib import pyplot as plt
import collections
%matplotlib inline

def live_plot(data_dict, figsize=(7,5), title=''):
    clear_output(wait=True)
    plt.figure(figsize=figsize)
    for label,data in data_dict.items():
        plt.plot(data, label=label)
    plt.title(title)
    plt.grid(True)
    plt.xlabel('epoch')
    plt.legend(loc='center left') # the plot evolves to the right
    plt.show();

Then in a loop you populate a dictionary and you pass it to live_plot():

然后在循环中填充字典并将其传递给live_plot()

data = collections.defaultdict(list)
for i in range(100):
    data['foo'].append(np.random.random())
    data['bar'].append(np.random.random())
    data['baz'].append(np.random.random())
    live_plot(data)

make sure you have a few cells below the plot, otherwise the view snaps in place each time the plot is redrawn.

确保绘图下方有几个单元格,否则每次重新绘制绘图时视图都会捕捉到位。