简体   繁体   English

散景| Jupyter笔记本| Python | 情节未显示

[英]Bokeh | Jupyter Notebook | Python | Plot Not Showing

I've spent the last few weeks learning the Bokeh package (which for visualizations, is excellent in my opinion). 我花了最后几个星期来学习Bokeh软件包(对于可视化来说,这是非常好的)。

Unfortunately, I have come across a problem that I can't for the life of me, figure out how to solve. 不幸的是,我遇到了一个我一生无法解决的问题,想出了解决方法。

The below two links have been helpful, but I can't seem to replicate for my problem. 下面的两个链接很有帮助,但是我似乎无法为我的问题重复。

Using bokeh to plot interactive pie chart in Jupyter/Python - refer to answer #3 在Jupyter / Python中使用bokeh绘制交互式饼图 -请参阅答案#3

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

The below code (in Jupyter) displays the graph correctly and displays the slider correctly, but I'm unsure how to connect the two as when I move the slider, the graph remains static. 下面的代码(在Jupyter中)正确显示了图形并正确显示了滑块,但是我不确定如何连接两者,因为当我移动滑块时,图形保持静态。

I am using Python 3.6 and Bokeh 12.9 我正在使用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)

After reading the bokeh documentation and reading a view threads on GitHub, the 'callback' function is a little unclear for me as I'm not entirely sure what to parse to it (if in fact attr, old, new need certain elements parsed too it) 在阅读bokeh文档并在GitHub上阅读了视图线程之后,“回调”功能对我来说还是有点不清楚,因为我不确定要解析什么(实际上,如果attr,old,new也需要解析某些元素)它)

Any help would be greatly appreciated 任何帮助将不胜感激

Hopefully, I haven't missed anything glaringly obvious. 希望我没有错过任何显而易见的事情。

Kind Regards, 亲切的问候,

Adrian 阿德里安

I suppose your question relates to the server although you have both a CustomJS and a server callback. 我想您的问题与服务器有关,尽管您同时具有CustomJS和服务器回调。

I am not familiar with the previous way of doing bokeh server in notebook ( push_notebook ). 我不熟悉在笔记本( push_notebook )中做bokeh服务器的先前方法。 The new way would be like this: you wrap your code in a function taking one parameter (a document) and your call to add_layout is made on that document. 新的方法是这样的:将代码包装在带有一个参数(一个文档)的函数中,并在该文档上调用add_layout Then you build an app with that function and show it. 然后,您使用该功能构建一个应用程序并显示它。

This gives: 这给出:

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")

You are currently mixing different ways for interactivity but unfortunately you always miss something for each different way. 当前,您正在混合使用不同的交互方式,但是不幸的是,您总是会错过每种不同方式的东西。

The slider you use is from bokeh, but unfortunately it looks like slider.on_change only works if you run through the bokeh server. 您使用的滑块来自bokeh,但不幸的是,它看起来类似于slider.on_change仅在通过bokeh服务器运行时才有效。 From the documentation : 文档中

Use bokeh serve to start the Bokeh server and set up event handlers with .on_change (or for some widgets, .on_click). 使用bokeh serve启动Bokeh服务器,并使用.on_change(或对于某些小部件,.on_click)设置事件处理程序。

I couldn't really find that much on running jupyter notebook and bokeh server, but this issue seems to discuss that possibility. 我在运行jupyter笔记本和bokeh服务器上找不到太多,但是这个问题似乎在讨论这种可能性。 It also mentions bokeh.application but I've never used that, so no idea how that works. 它还提到bokeh.application ,但我从未使用过,所以不知道如何工作的。

You also use additionally a custom js callback, which calls into the jupyter kernel and tries to execute update_plot(value) , but you never defined such a function, so it does nothing. 您还另外使用了一个自定义js回调,该回调调用jupyter内核并尝试执行update_plot(value) ,但是您从未定义过此类函数,因此它什么也不做。

Then you need a method to push the data to the output. 然后,您需要一种将数据推送到输出的方法。 I guess bokeh server can somehow do that nativly, for jupyter notebooks without the bokeh server push_notebook seems to be the solution. 我猜想bokeh服务器可以以某种方式天真地做到这一点,对于没有bokeh服务器的push_notebook笔记本, push_notebook似乎是解决方案。 Note that you need show(..., notebook_handle=True) to be able to push. 请注意,您需要show(..., notebook_handle=True)才能进行推送。

Solution 1 use the bokeh server 解决方案1使用背景虚化服务器

Sliders and others widgets automatically sync their state back to python, so you can use slider.on_change . 滑条和其他自动部件同步他们的状态恢复到蟒蛇,所以你可以使用slider.on_change You don't need the CustomJS. 你不需要CustomJS。 Data flow should look as following: 数据流应如下所示:

python script -> bokeh server -> html -> userinput -> bokeh server -> python callbacks -> bokeh server updates plots

Solution 2 use bokeh sliders but sync via CustomJS 解决方案2使用bokeh滑块,但通过CustomJS同步

If you don't want to run a seperate process you can use the jupyter kernel to execute code in your python notebook. 如果您不想运行单独的进程,则可以使用jupyter内核在python笔记本中执行代码。 Dataflow: 数据流:

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)

Solution 3 use ipywidgets 解决方案3使用ipywidgets

If you are not married to the bokeh widgets you can use the ipywidgets which are designed for interactivity in the jupyter notebook. 如果您不喜欢bokeh小部件,则可以在jupyter笔记本中使用为交互性而设计的ipywidget。 The data flow is as following: 数据流如下:

jupyter notebook -> html -> user input -> ipywidgets sync automatically -> python callbacks -> push_notebook

I use here interact but the other widgets should work as expected. 我在这里使用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)

Note that you need to install ipywidgets properly, which inlcudes calling jupyter nbextension enable --py --sys-prefix widgetsnbextension if you are not using conda. 请注意,您需要正确安装ipywidgets,如果不使用jupyter nbextension enable --py --sys-prefix widgetsnbextension则需要调用jupyter nbextension enable --py --sys-prefix widgetsnbextension For details see the documentation 有关详细信息, 请参阅文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM