interact and plotting with ipywidgets events produces many graphs

孤者浪人 提交于 2019-12-22 10:16:04

问题


I am trying to use widget events to make an interactive graph.

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

import ipywidgets as widgets

def myplot(n):
    x = np.linspace(-5, 5, 30)
    y = x**n

    fig, ax = plt.subplots(nrows=1, ncols=1);
    ax.plot(x, y)
    ax.set_xlabel('x')
    ax.set_ylabel('y')

    plt.show()

Interact works as expected (it changes the figure interactively):

widgets.interact(myplot, n=(0,5));

However the following snippet creates several figures that appear below as you interact with the slider.

n_widget = widgets.IntSlider(
                value=2,
                min=0,
                max=5)

def on_value_change(change):
    myplot(n=n_widget.value)

n_widget.observe(on_value_change)
display(n_widget)

Can I update the plot as if I were using widgets.interact()?


My current installation is with conda and Python 3.6 (windows machine).

ipywidgets                7.1.0                     
jupyter                   1.0.0              
jupyter_client            5.2.1                  
jupyter_console           5.2.0             
jupyter_core              4.4.0              
matplotlib                2.1.1             
notebook                  5.3.1               
numpy                     1.14.0     

回答1:


Note that the below is a working solution for ipywidgets version < 7.0. For a solution with ipywidgets >= 7.0 see this GitHub issue.

While in many simple cases plt.show() works nicely replacing the output of a cell, this is not always the case. When using interactive elements in Jupyter it is often more helpful to use IPython.display.display.

Here you may not want to create a new plot for each interaction. Instead just setting new data to the plot is enough. Then you may autoscale the plot for the new data and display the figure. You may use IPython.display.clear_output to clear the output once a new figure would be displayed. This ensures to have always a single plot present in the output cell, independent of the use of interact or observe.

def myplot(n):
    line.set_ydata(x**n)
    ax.relim()
    ax.autoscale()
    display(fig)
    clear_output(wait=True)

Comlpete notebook:

# cell 1
%%capture
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display, clear_output
import ipywidgets as widgets

fig, ax = plt.subplots(nrows=1, ncols=1);
x = np.linspace(-5, 5, 30)
y = x**0

line, = ax.plot(x, y)
ax.set_xlabel('x')
ax.set_ylabel('y')

def myplot(n):
    line.set_ydata(x**n)
    ax.relim()
    ax.autoscale()
    display(fig)
    clear_output(wait=True)

#cell2
widgets.interact(myplot, n=(0,5));

#cell3
n_widget = widgets.IntSlider(
                value=2,
                min=0,
                max=5)

def on_value_change(change):
    myplot(n=n_widget.value)

n_widget.observe(on_value_change)
display(n_widget)



来源:https://stackoverflow.com/questions/48380967/interact-and-plotting-with-ipywidgets-events-produces-many-graphs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!