背景虚化 | Jupyter 笔记本 | Python |情节不显示
Bokeh | Jupyter Notebook | Python | Plot Not Showing
过去几周我一直在学习 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 中)正确显示了图形并正确显示了滑块,但我不确定如何连接这两者,因为当我移动滑块时,图形保持静态。
我正在使用 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)
阅读散景文档并阅读 GitHub 上的视图线程后,'callback' 函数对我来说有点不清楚,因为我不完全确定要解析什么(如果在事实上 attr, old, new 也需要解析某些元素)
如有任何帮助,我们将不胜感激
希望我没有遗漏任何明显的东西。
亲切的问候,
阿德里安
尽管您同时拥有 CustomJS 和服务器回调,但我想您的问题与服务器有关。
我不熟悉以前在notebook中做bokeh server的方法(push_notebook
)。
新方法是这样的:将代码包装在一个函数中,该函数接受一个参数(一个文档),然后对 add_layout
的调用是在该文档上进行的。然后你用那个函数构建一个应用程序并展示它。
这给出:
from bokeh.models import ColumnDataSource, Slider
from bokeh.layouts import column
from bokeh.plotting import figure, show, output_notebook
from numpy.random import random
from bokeh.application import Application
from bokeh.application.handlers import FunctionHandler
output_notebook()
def modify_doc(doc):
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)
slider = Slider(start=100, end=1000, value=N, step=10)
def callback(attr, old, new):
N = new # but slider.value would also work
source.data={'x': random(N), 'y': random(N)}
slider.on_change('value', callback)
layout = column(slider, plot)
doc.add_root(layout)
app = Application(FunctionHandler(modify_doc))
show(app, notebook_url="localhost:8888")
您目前正在混合不同的交互方式,但不幸的是,您总是会错过每种不同方式的一些东西。
您使用的滑块来自散景,但不幸的是,它看起来 slider.on_change
只有在您 运行 通过散景服务器时才有效。来自 documentation:
Use bokeh serve to start the Bokeh server and set up event handlers with .on_change (or for some widgets, .on_click).
我在 运行ning jupyter notebook 和 bokeh 服务器上真的找不到那么多,但 this issue 似乎讨论了这种可能性。它还提到 bokeh.application
但我从未使用过它,所以不知道它是如何工作的。
您还额外使用了一个自定义的 js 回调,它调用 jupyter 内核并尝试执行 update_plot(value)
,但您从未定义过这样的函数,因此它什么也不做。
然后你需要一个方法来将数据推送到输出。我想散景服务器可以以某种方式自然地做到这一点,对于没有散景服务器的 jupyter 笔记本 push_notebook
似乎是解决方案。请注意,您需要 show(..., notebook_handle=True)
才能推送。
方案一使用散景服务器
滑块和其他小部件会自动将它们的状态同步回 python,因此您可以使用 slider.on_change
。你不需要 CustomJS。数据流应如下所示:
python script -> bokeh server -> html -> userinput -> bokeh server -> python callbacks -> bokeh server updates plots
解决方案 2 使用散景滑块但通过 CustomJS 同步
如果您不想 运行 一个单独的进程,您可以使用 jupyter 内核在 python 笔记本中执行代码。数据流:
jupyter notebook -> html -> user input -> customjs -> jupyter kernel -> python callbacks -> push_notebook to update plots
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
如果您不喜欢散景小部件,您可以使用专为在 jupyter 笔记本中进行交互而设计的 ipywidgets。数据流向如下:
jupyter notebook -> html -> user input -> ipywidgets sync automatically -> python callbacks -> 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
过去几周我一直在学习 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 中)正确显示了图形并正确显示了滑块,但我不确定如何连接这两者,因为当我移动滑块时,图形保持静态。
我正在使用 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)
阅读散景文档并阅读 GitHub 上的视图线程后,'callback' 函数对我来说有点不清楚,因为我不完全确定要解析什么(如果在事实上 attr, old, new 也需要解析某些元素)
如有任何帮助,我们将不胜感激
希望我没有遗漏任何明显的东西。
亲切的问候,
阿德里安
尽管您同时拥有 CustomJS 和服务器回调,但我想您的问题与服务器有关。
我不熟悉以前在notebook中做bokeh server的方法(push_notebook
)。
新方法是这样的:将代码包装在一个函数中,该函数接受一个参数(一个文档),然后对 add_layout
的调用是在该文档上进行的。然后你用那个函数构建一个应用程序并展示它。
这给出:
from bokeh.models import ColumnDataSource, Slider
from bokeh.layouts import column
from bokeh.plotting import figure, show, output_notebook
from numpy.random import random
from bokeh.application import Application
from bokeh.application.handlers import FunctionHandler
output_notebook()
def modify_doc(doc):
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)
slider = Slider(start=100, end=1000, value=N, step=10)
def callback(attr, old, new):
N = new # but slider.value would also work
source.data={'x': random(N), 'y': random(N)}
slider.on_change('value', callback)
layout = column(slider, plot)
doc.add_root(layout)
app = Application(FunctionHandler(modify_doc))
show(app, notebook_url="localhost:8888")
您目前正在混合不同的交互方式,但不幸的是,您总是会错过每种不同方式的一些东西。
您使用的滑块来自散景,但不幸的是,它看起来 slider.on_change
只有在您 运行 通过散景服务器时才有效。来自 documentation:
Use bokeh serve to start the Bokeh server and set up event handlers with .on_change (or for some widgets, .on_click).
我在 运行ning jupyter notebook 和 bokeh 服务器上真的找不到那么多,但 this issue 似乎讨论了这种可能性。它还提到 bokeh.application
但我从未使用过它,所以不知道它是如何工作的。
您还额外使用了一个自定义的 js 回调,它调用 jupyter 内核并尝试执行 update_plot(value)
,但您从未定义过这样的函数,因此它什么也不做。
然后你需要一个方法来将数据推送到输出。我想散景服务器可以以某种方式自然地做到这一点,对于没有散景服务器的 jupyter 笔记本 push_notebook
似乎是解决方案。请注意,您需要 show(..., notebook_handle=True)
才能推送。
方案一使用散景服务器
滑块和其他小部件会自动将它们的状态同步回 python,因此您可以使用 slider.on_change
。你不需要 CustomJS。数据流应如下所示:
python script -> bokeh server -> html -> userinput -> bokeh server -> python callbacks -> bokeh server updates plots
解决方案 2 使用散景滑块但通过 CustomJS 同步
如果您不想 运行 一个单独的进程,您可以使用 jupyter 内核在 python 笔记本中执行代码。数据流:
jupyter notebook -> html -> user input -> customjs -> jupyter kernel -> python callbacks -> push_notebook to update plots
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
如果您不喜欢散景小部件,您可以使用专为在 jupyter 笔记本中进行交互而设计的 ipywidgets。数据流向如下:
jupyter notebook -> html -> user input -> ipywidgets sync automatically -> python callbacks -> 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