在笔记本和JupyterLab中的交互式绘图

huangapple go评论63阅读模式
英文:

interactive plot in notebook vs jupyterlab

问题

使用Jupyter Notebook 6.5.4、Python 3.8.13和IPython 8.12.0,我可以创建一个交互式图表:

from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook 
# inline在Jupyter Notebook中不起作用
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
fig, ax = plt.subplots(figsize=(6,4))
x = np.linspace(-10, 10, num=1000)
l, = ax.plot(x, r_widget.value * x + c_widget.value)
ax.set_ylim(-5, 5)
def f(m, b):
    l.set_ydata(m*x+b) 
    fig.canvas.draw()
interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

通过滑动小部件,我可以进行平移/缩放并更新交互式图表。我认为这种技术更好/更快/更高效,因为我不是在每次调整滑块时创建图表,而是只更新线条数据。此外,我发现如果不直接更新线条数据,每次更新都会产生新的线条,而不仅仅是改变线条。

我切换到了JupyterLab 3.6.3,有一些人问及JupyterLab和Jupyter Notebook之间的交互式绘图差异,但是那些解决方案是3-4年前的,不能解决我的问题。

在JupyterLab中,我只能使用%matplotlib inline并按照以下方式使用interactive

%matplotlib inline  
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

使用%matplotib notebook%matplotlib widget都会出现Javascript Error: IPython is not defined错误。如果我将fig, ax = plt.subplots(figsize=(6,4))移到函数f上面,图表将不显示。

这个答案没有改变我描述的行为。我使用的是ipympl 0.9.3

我不应该期望我的旧式交互式绘图方法能够工作吗?除了能够平移/缩放之外,还有其他优势吗?

英文:

With Jupyter Notebook 6.5.4, Python 3.8.13, IPython 8.12.0, I can make an interactive plot with:

from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook 
#inline doesn't work in jupyter notebook 
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
fig, ax = plt.subplots(figsize=(6,4))
x = np.linspace(-10, 10, num=1000)
l, = ax.plot(x, r_widget.value * x + c_widget.value)
ax.set_ylim(-5, 5)
def f(m, b):
    l.set_ydata(m*x+b) 
    fig.canvas.draw()
interactive_plot = interactive(f, m = m_widget, b=b_widget )
interactive_plot 

and the interactive plot works with pan/zoom and updates as I slide the widgets.
I thought this technique would be better/faster/more efficient since I am not creating the figure with each slider adjustment, but instead only updating the line data. Also, I found if I didn't update the line data directly, I would end up with new lines on each update, instead of just changing the line.
I switched to jupyterlab 3.6.3, and a few others have asked about the differences with interactive plotting between jupyterlab and jupyter notebook, however those solutions are 3-4 years old and are not solving my issue.
In jupyterlab, I can only get interactive to work with %matplotlib inline and in the following style:

%matplotlib inline  
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

Using %matplotib notebook and %matplotlib widget both result in Javascript Error: IPython is not defined. If I move the fig, ax = plt.subplots(figsize=(6,4)) above the function f, the plot does nothing.
This answer has not changed the behavior I'm describing. I have ipympl 0.9.3.
Should I not expect my older style of making interactive plots to work? Is there even an advantage to that (besides being able to pan/zoom)?

答案1

得分: 0

在JupyterLab 3.4.8中,以下两种变体的第二个代码块可以同时具有pan/zoom等“交互性”选项和ipywidgets对图表的交互性。

%matplotlib ipympl
from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

这是安装了ipympl的位置。

另外一种方法也可以实现:

%matplotlib widget
from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

这是因为如ipympl文档中的“基本示例”部分所解释的那样:

>“要激活ipympl后端,您只需要在笔记本中包含%matplotlib ipympl魔术命令。或者,您可以使用%matplotlib widget,其效果相同。”

我可以引导您到一个地方,将您看到的内容与您应该看到的内容进行比较。点击这里,在会话启动后,打开一个新的笔记本并运行您的第二个代码块。这是安装了ipympl的JupyterLab 3.4.8(目前是这样,但随着时间的推移会发生变化,因为它不是锁定的)。

我已经验证了相同的两个代码块在JupyterLab 4.0.3中也可以工作。您可以通过点击这里获取一个安装了ipympl的JupyterLab 4.0.3会话来自行验证。

顺便说一句,这个“交互式图表”展示了两种类型的交互性。它既展示了matplotlib的交互特性(即“ipympl风格的交互性”),也展示了通过浮动滑块小部件控制图表更新的ipywidget交互性。在这里可以看到“ipympl风格的交互性”的示例,也就是matplotlib的交互特性,点击这里。在这里可以找到有关使用ipywidget的interactinteractive自动创建用户界面(UI)控件以交互式地探索代码和数据的讨论和更多示例。

英文:

In JupyterLab 3.4.8, the following variations of your second code block works to have both the pan/zoom, etc. 'interactivity' options and the ipywidgets interactivity of the plot.

%matplotlib ipympl
from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

This is where ipympl is installed.

This also works:

%matplotlib widget
from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

This is because as explained 'Basic Example' section in the documentation for ipympl here:

>"To activate the ipympl backend all you need to do is include the %matplotlib ipympl magic in the notebook. Alternatively you can use %matplotlib widget which will have the same effect."

I can direct you to a place to compare what you see with what you should see. Click here and after session starts up, open a new notebook and run your second code block. That is JupyterLab 3.4.8 (presently -- it will change over time because it isn't locked) with ipympl installed.

I have verified that the same two code blocks will also work in JupyterLab 4.0.3, too. You can demonstrate that for yourself by clicking here to get a session with JupyterLab 4.0.3 with ipympl installed.
I'll note that to make a version of a MyBinder session that has ipympl installed properly, I had to add before build & launch as it is tricky install and doesn't work if installed later in a running session. In fact, a situation similar to this is probably what you may be seeing because the result, giving javascript error, is similar to what you report.


By the way, this 'interactive plot' is showing two types of interactivity. It exhibits both the interactive features of matplotlib ('ipympl-style interactivity') and ipywidget interactivity in controlling updating of the plot via floating slider widget controller. See an example of 'ipympl-style interactivity', in other words the interactive features of matplotlib, here and see here for a discussion with further examples of using ipywidget's interact and interactive to automatically creates user interface (UI) controls for exploring code and data interactively.

答案2

得分: 0

我找到了这个讨论,所以我执行了conda install nodejs命令,现在我问题中的第一个代码块可以使用%matplotlib widget%matplotlib ipympl两种交互方式(小部件和平移/缩放)。

英文:

I found this discussion and so I did conda install nodejs and now the first code block in my question works with %matplotlib widget and also %matplotlib ipympl, with both types of interaction (the widgets and the pan/zoom).

huangapple
  • 本文由 发表于 2023年8月8日 21:51:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860211.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定