2017-10-03 10 views
1

나는 지난 몇 주 동안 시각화를 위해 Bokeh 패키지를 배우는 데 보냈다.보케 (Bokeh) | 주피터 수첩 | 파이썬 | 플롯 표시 안 함

불행히도, 나는 삶의 방식으로는 해결할 수없는 문제를 발견했습니다. 해결 방법을 찾아야합니다.

아래의 두 링크가 도움이되었지만 문제에 대해 복제 할 수 없습니다.

Using bokeh to plot interactive pie chart in Jupyter/Python - 제대로 그래프를 표시하고 올바르게 슬라이더를 표시 #에게 (Jupyter에서) 3

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

아래의 코드를 답변을 참조하지만 같은 두 가지를 연결하는 방법을 확실 해요 I 슬라이더를 움직이면 그래프는 정적으로 유지됩니다. 내가 완전히 확실하지 않다으로

나는 나뭇잎 문서를 읽고 GitHub의에보기 스레드를 읽은 후 파이썬 3.6 보케 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) 

를 사용하고는 '콜백'기능은 나를 위해 조금 불분명하다 (사실 ATTR, 오래된, 새로운 필요 특정 요소가 너무 그것을 해석하는 경우)

여기에 무엇을 구문 분석하는 어떤 도움이 크게 될 눈부시게 분명

희망, 내가 놓친하지 않은 것을 감사합니다.

친절 감사를

아드리안

+0

[this] (https://bokeh.pydata.org/en/latest/docs/user_guide/notebook.html#jupyter-interactors) 가이드를 보았습니까? 중요한 'push_notebook'이 누락되었습니다. – syntonym

+0

답장을 보내 주셔서 감사합니다. Jupyter에서이 코드를 실행했으며 완벽하게 작동합니다. 그러나 push_notebook을 내 코드에 추가해도 아무런 변화가 없습니다. 이걸 당신 기계에서 실행 했습니까? – AdrianC

+0

'show' 함수에서'notebook_handle = True'도 필요하다고 생각합니다. 현재 귀하의 코드를 실행할 수는 없지만 아무도 당신을 도울 수없는 경우 오늘 저녁에 보겠습니다. 예를 들어 가져 오기 등을 추가하여 더 많은 사람들이 당신을 조속히 도와 줄 수 있습니다. 나는 왜 당신이 커스텀 js 콜백을하고 있는지 확실하지 않다. 아마도 웨지 예제에서? 제 생각에는'plot.circle'은 필요 없다고 생각하지만 오늘 저녁 테스트 만 할 수 있습니다. – syntonym

답변

3

은 현재 상호 작용을위한 여러 가지 방법을 혼합하고 있지만 불행하게도 당신은 항상 각각 다른 방식으로 뭔가를 그리워.

사용하는 슬라이더는 bokeh이지만, 불행히도 slider.on_change은 bokeh 서버를 실행하는 경우에만 작동합니다. documentation에서 :

사용 나뭇잎은 보케 서버를 시작하고 .on_change (또는 위젯, .on_click)와 이벤트 핸들러를 설정하는 역할을한다.

실제로 나는 jupyter 노트북과 bokeh 서버를 실행하는 데 그다지 많은 것을 찾을 수 없었지만, this issue은 그 가능성을 논의하는 것으로 보입니다. 그것은 또한 bokeh.application을 언급하지만 결코 사용하지 못했습니다. 그래서 어떻게 작동하는지 모르겠습니다.

또한 jupyter 커널을 호출하고 update_plot(value)을 실행하려고하는 사용자 정의 js 콜백을 추가로 사용하지만 사용자 정의 콜백은 아무 것도하지 않으므로 이러한 기능을 정의하지 않았습니다.

그런 다음 데이터를 출력으로 푸시해야합니다. 나는 bokeh 서버가 어떻게 든 그럴 수 있다고 생각한다. bokeh 서버가없는 jupyter 노트북의 경우 push_notebook가 해결책 인 것 같다. 푸시 할 수 있으려면 show(..., notebook_handle=True)이 필요합니다.

해결 방법 1 명을 사용하면 slider.on_change을 사용할 수 있도록

슬라이더와 다른 사람이 다시 파이썬으로 자신의 상태를 자동으로 동기화 위젯 보케 서버. CustomJS가 필요하지 않습니다. 데이터 흐름은 다음과 같아야합니다

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

솔루션 2 개를 사용 나뭇잎 슬라이더하지만 동기화를 CustomJS

를 통해 당신이 코드를 실행하기 위해 jupyter 커널을 사용할 수있는 별도의 프로세스를 실행하지 않으려면 귀하의 파이썬 노트북. 데이터 흐름 :

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) 

해결 방법 3을 사용 ipywidgets 당신이 jupyter 노트북의 상호 작용을 위해 설계되어 ipywidgets를 사용할 수있는 나뭇잎 위젯 결혼하지 않는 경우

. 데이터 흐름은 다음과 같습니다 :

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

내가 여기 interact 사용하지만 예상대로 다른 위젯이 작동합니다. 당신이 CONDA을 사용하지 않는 경우 jupyter nbextension enable --py --sys-prefix widgetsnbextension를 호출 inlcudes 제대로 ipywidgets를 설치해야

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) 

참고. 자세한 내용은 see the documentation

+0

솔루션 2가 완벽하게 작동합니다. 저를 도와 주시고 철저한 설명을 해주셔서 감사합니다. 당신의 친절. 내 자신의 지식은 더 많지만 솔루션 1은 솔루션 2보다 장단점이 있습니까? 나는이 대답이 주관적이고 내가 성취하고자하는 바에 달려 있다고 생각합니다. 개인적인 견해 나 모범 사례를 공유 할 수 있다면 그것이 좋을 것입니다. 질문을하기 전에 Solution 3을 시도했지만 Bokeh Dashboards를 구축하기 시작했다면 유연성이별로 좋지 않다고 생각했습니다. – AdrianC

+0

CustomJS 과정은 ipython이있을 때만 작동하므로 "순수 웹 응용 프로그램"bokeh 서버로 이동하려면 이동하는 것이 좋습니다. 나는 bokeh 서버를 한번도 시도한 적이 없지만 실제로 alex 대답처럼 간단하다면 분명히 시도 할 것입니다. 그것은 정말로 당신이하고 싶은 것에 달려 있습니다. – syntonym

2

나는 당신이 CustomJS와 서버 콜백 모두 가지고 있지만 귀하의 질문에 서버 관련 가정합니다.

나는 노트북 (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") 
+0

bokeh에서 새로운 방식에 대한 정보를 찾을 수 없었습니다. 이미 사용자 가이드에 문서화되어 있습니까? 아니면 현재 API 문서에만 있습니까? 이것은 또한 jupyter 노트북이나 bokeh 서버에서만 작동합니까? – syntonym

+0

이 예제는 노트북에서 실행되며 기본적으로 '앱'을 제공하는 서버 프로세스 (또는 확실하지 않은 스레드)를 실행합니다. 내가 아는 한, 이것은 완전히 문서화되어 있지 않다. (특히 사용자 가이드에서) – Alex

+0

수정 : 실제로 [여기] (https://bokeh.pydata.org/en/latest/docs/user_guide/ server.html # embedding-bokeh-server-as-a-library)를 [예제] (https://github.com/bokeh/bokeh/tree/0.12.9/examples/howto/server_embed/notebook_embed)와 연결하십시오.ipynb) – Alex