В ответах на вопрос, как динамически обновлять график в цикле в записной книжке ipython (в пределах одной ячейки) , приводится пример динамического обновления графика внутри записной книжки Jupyter в цикле Python. Однако это работает путем разрушения и воссоздания сюжета на каждой итерации, и в комментарии в одном из потоков отмечается, что эту ситуацию можно улучшить, используя новую %matplotlib nbagg
магию, которая предоставляет интерактивную фигуру, встроенную в записную книжку, а не чем статичное изображение.
Однако эта замечательная новая nbagg
функция кажется полностью недокументированной, насколько я могу судить, и я не могу найти пример того, как использовать ее для динамического обновления графика. Таким образом, мой вопрос: как эффективно обновить существующий график в записной книжке Jupyter / Python, используя бэкэнд nbagg? Поскольку динамическое обновление графиков в matplotlib в целом является сложной задачей, простой рабочий пример будет огромным подспорьем. Указатель на любую документацию по теме также был бы чрезвычайно полезен.
Чтобы прояснить, о чем я прошу: я хочу запустить некоторый код моделирования для нескольких итераций, затем нарисовать график его текущего состояния, затем запустить его еще несколько итераций, а затем обновить график, чтобы отразить текущее состояние и так далее. Таким образом, идея состоит в том, чтобы нарисовать график, а затем, без какого-либо взаимодействия с пользователем, обновить данные на графике, не разрушая и не создавая заново все это.
Вот немного измененный код из ответа на связанный выше вопрос, который достигает этого, каждый раз заново отрисовывая всю фигуру. Хочу добиться того же результата, но более эффективно используя 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)
источник
while True:
на цикл for, по окончании цикла я получу два статических изображения последнего сюжета, а не интерактивное изображение nbagg. Есть идеи, почему это так?plt.show()
и перемещал цикл for в следующую ячейку.Я использую 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();
Затем в цикле вы заполняете словарь и передаете его
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)
убедитесь, что у вас есть несколько ячеек под графиком, в противном случае вид будет фиксироваться на месте каждый раз, когда график перерисовывается.
источник
Я адаптировал ответ @Ziofil и изменил его, чтобы принимать x, y в качестве списка и выводить диаграмму рассеяния плюс линейный тренд на том же графике.
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();
вам просто нужно вызвать
live_plot(x, y)
внутри цикла. вот как это выглядит:источник