Skip to main content
 首页 » 编程设计

python之背景虚化 | Jupyter 笔记本 | python |情节不显示

2025年05月04日24lidabo

过去几周我一直在学习 Bokeh 包(我认为它在可视化方面非常出色)。

不幸的是,我遇到了一个我一生都无法解决的问题。

以下两个链接很有帮助,但我似乎无法复制我的问题。

Using bokeh to plot interactive pie chart in Jupyter/Python - 引用答案#3

https://github.com/bokeh/bokeh/blob/0.12.9/examples/howto/notebook_comms/Jupyter%20Interactors.ipynb

下面的代码(在 Jupyter 中)正确显示了图形并正确显示了 slider ,但我不确定如何将两者连接起来,因为当我移动 slider 时,图形保持静态。

我正在使用 Python 3.6 和 Bokeh 12.9

N = 300 
 
source = ColumnDataSource(data={'x':random(N), 'y':random(N)})  
 
plot = figure(plot_width=950, plot_height=400)  
 
plot.circle(x='x', y='y', source=source) 
 
callback = CustomJS(code="""  
if (IPython.notebook.kernel !== undefined) { 
    var kernel = IPython.notebook.kernel; 
    cmd = "update_plot(" + cb_obj.value + ")"; 
    kernel.execute(cmd, {}, {})};  
""") 
 
slider = Slider(start=100, end=1000, value=N, step=10, callback=callback) 
 
def callback(attr, old, new): 
    N = slider.value 
    source.data={'x':random(N), 'y':random(N)} 
 
slider.on_change('value', callback) 
 
layout = column(slider, plot)  
 
curdoc().add_root(layout) 
 
show(widgetbox(slider, width = 300))  
 
show(plot) 

在阅读了 bokeh 文档并阅读了 GitHub 上的 View 线程后,“回调”函数对我来说有点不清楚,因为我不完全确定要解析什么(如果实际上 attr、old、new 需要某些元素也被解析了)

任何帮助将不胜感激

希望我没有遗漏任何明显的东西。

亲切的问候,

阿德里安

请您参考如下方法:

您目前正在混合不同的交互方式,但不幸的是,您总是会错过每种不同方式的一些东西。

您使用的 slider 来自 Bokeh ,但不幸的是,它看起来像 slider.on_change 只有在您通过 Bokeh 服务器运行时才有效。来自documentation :

Use bokeh serve to start the Bokeh server and set up event handlers with .on_change (or for some widgets, .on_click).

我在运行 jupyter notebook 和 bokeh 服务器上真的找不到那么多,但是 this issue似乎在讨论这种可能性。它还提到了 bokeh.application 但我从未使用过它,所以不知道它是如何工作的。

您还额外使用了自定义 js 回调,它调用 jupyter 内核并尝试执行 update_plot(value),但您从未定义过这样的函数,因此它什么也不做。

然后您需要一种将数据推送到输出的方法。我想 Bokeh 服务器可以以某种方式自然地做到这一点,对于没有 Bokeh 服务器 push_notebook 的 jupyter notebooks 似乎是解决方案。请注意,您需要 show(..., notebook_handle=True) 才能推送。

方案一使用 Bokeh 服务器

slider 和其他小部件会自动将它们的状态同步回 python,因此您可以使用 slider.on_change。你不需要 CustomJS。数据流应如下所示:

python 脚本 -> bokeh 服务器 -> html -> userinput -> bokeh 服务器 -> python 回调 -> bokeh 服务器更新绘图

解决方案 2 使用 Bokeh slider 但通过 CustomJS 同步

如果您不想运行单独的进程,您可以使用 jupyter 内核在 python 笔记本中执行代码。数据流:

jupyter notebook -> html -> 用户输入 -> customjs -> jupyter 内核 -> python 回调 -> push_notebook 更新绘图

output_notebook() 
 
N = 300 
 
source = ColumnDataSource(data={'x':random(N), 'y':random(N)})  
 
plot = figure(plot_width=950, plot_height=400)  
 
plot.circle(x='x', y='y', source=source) 
 
callback = CustomJS(code="""  
if (IPython.notebook.kernel !== undefined) { 
    var kernel = IPython.notebook.kernel; 
    cmd = "update_plot(" + cb_obj.value + ")"; 
    kernel.execute(cmd, {}, {})};  
""") 
 
slider = Slider(start=100, end=1000, value=N, step=10, callback=callback) 
 
# must have the same name as the function that the CustomJS tries to call 
def update_plot(N): 
    source.data={'x':random(N), 'y':random(N)} 
    # push notebooks to update plots 
    push_notebook() 
 
layout = column(slider, plot)  
# notebook_handle must be true, otherwise push_notebook will not work 
h1 = show(layout, notebook_handle=True) 

方案三使用ipywidgets

如果您不喜欢 Bokeh 小部件,您可以使用专为在 jupyter 笔记本中进行交互而设计的 ipywidgets。数据流向如下:

jupyter notebook -> html -> 用户输入 -> ipywidgets 自动同步 -> python 回调 -> push_notebook

我在这里使用 interact 但其他小部件应该按预期工作。

from ipywidgets import interact 
 
output_notebook() 
 
N = 300 
 
source = ColumnDataSource(data={'x':random(N), 'y':random(N)})  
 
plot = figure(plot_width=950, plot_height=400)  
 
plot.circle(x='x', y='y', source=source) 
 
def update_plot(v): 
    N = v 
    print(N) 
    source.data={'x':random(N), 'y':random(N)} 
    # push changed plots to the frontend 
    push_notebook() 
 
# notebook_handle must be true so that push_notebook works 
show(plot, notebook_handle=True) 

请注意,您需要正确安装 ipywidgets,如果您不使用 conda,这包括调用 jupyter nbextension enable --py --sys-prefix widgetsnbextension。详情see the documentation