Nas respostas sobre como atualizar dinamicamente um gráfico em um loop no notebook ipython (dentro de uma célula) , é dado um exemplo de como atualizar dinamicamente um gráfico dentro de um notebook Jupyter dentro de um loop Python. No entanto, isso funciona destruindo e recriando o enredo em cada iteração, e um comentário em um dos tópicos observa que esta situação pode ser melhorada usando a %matplotlib nbagg
magia nova , que fornece uma figura interativa embutida no caderno, ao invés do que uma imagem estática.
No entanto, esse novo nbagg
recurso maravilhoso parece ser completamente indocumentado, pelo que posso dizer, e não consigo encontrar um exemplo de como usá-lo para atualizar um enredo dinamicamente. Portanto, minha pergunta é: como atualizar com eficiência um gráfico existente em um notebook Jupyter / Python, usando o back-end nbagg? Visto que atualizar gráficos dinamicamente em matplotlib é uma questão complicada em geral, um exemplo simples de trabalho seria de grande ajuda. Uma indicação para qualquer documentação sobre o tópico também seria extremamente útil.
Para deixar claro o que estou pedindo: o que eu quero fazer é executar algum código de simulação para algumas iterações, em seguida, desenhar um gráfico de seu estado atual, executá-lo para mais algumas iterações e atualizar o gráfico para refletir o estado atual e assim por diante. Então a ideia é desenhar um enredo e depois, sem nenhuma interação do usuário, atualizar os dados do enredo sem destruir e recriar tudo.
Aqui está um código ligeiramente modificado da resposta à pergunta vinculada acima, que consegue isso redesenhando a figura inteira todas as vezes. Quero obter o mesmo resultado, mas com mais eficiência usando 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)
fonte
while True:
para um loop for, quando o loop terminar, obtenho duas imagens estáticas do último enredo, em vez de um nbagg interativo. Alguma ideia do porquê?plt.show()
e mover o loop for para a próxima célula.Estou usando o jupyter-lab e isso funciona para mim (adapte ao seu caso):
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();
Em seguida, em um loop, você preenche um dicionário e o passa para
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)
certifique-se de ter algumas células abaixo do gráfico, caso contrário, a visualização se encaixará cada vez que o gráfico for redesenhado.
fonte
Eu adaptei a resposta @Ziofil e a modifiquei para aceitar x, y como lista e gerar um gráfico de dispersão mais uma tendência linear no mesmo gráfico.
from IPython.display import clear_output from matplotlib import pyplot as plt %matplotlib inline def live_plot(x, y, figsize=(7,5), title=''): clear_output(wait=True) plt.figure(figsize=figsize) plt.xlim(0, training_steps) plt.ylim(0, 100) x= [float(i) for i in x] y= [float(i) for i in y] if len(x) > 1: plt.scatter(x,y, label='axis y', color='k') m, b = np.polyfit(x, y, 1) plt.plot(x, [x * m for x in x] + b) plt.title(title) plt.grid(True) plt.xlabel('axis x') plt.ylabel('axis y') plt.show();
você só precisa chamar
live_plot(x, y)
dentro de um loop. é assim que parece:fonte
Se não quiser limpar todas as saídas, você pode usar
display_id=True
para obter um identificador e usá.update()
-lo:import numpy as np import matplotlib.pyplot as plt import time from IPython import display def pltsin(ax, *,hdisplay, 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) hdisplay.update(fig) fig,ax = plt.subplots(1,1) hdisplay = display.display("", display_id=True) 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, colors=['b', 'r'], hdisplay=hdisplay) time.sleep(1) plt.close(fig)
(adaptado de @pneumatics)
fonte