我正在寻找一种方法来导出我的Jupyter笔记本,其中包含带有小部件的交互式Bokeh绘图到独立的HTML。当使用工具栏中的Jupyter NB“download to”HTML函数时,除了交互式Bokeh图之外的所有内容都可以导出,静态Bokeh图也可以导出(静态图也是“交互式”的,但底层数据不会更改)
如何使用独立HTML中的小部件获得交互式绘图?
下面您可以在安装了Bokeh 13.0的Jupyter笔记本中找到一个工作示例。
import numpy as np
import pandas as pd
from bokeh.io import save, curdoc,output_file ,show, output_notebook, push_notebook
from bokeh.plotting import figure, gridplot
from bokeh.models import ColumnDataSource, Panel
from bokeh.models.widgets import Slider, Tabs, DataTable, TableColumn
from bokeh.layouts import layout, WidgetBox
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
# output_file('tryout.html')
output_notebook()
# Static Bokeh plot:
data = pd.DataFrame(np.random.random([10,2]),columns=['x','y'])
dataMean = pd.DataFrame([],columns=['mean','std'])
dataMean.loc[:,'mean'] =data.mean()
dataMean.loc[:,'std'] =data.std()
src1 = ColumnDataSource(data)
src2 = ColumnDataSource(dataMean)
p = figure(plot_width = 700, plot_height = 400,
title = 'Test case',x_axis_label = 'x', y_axis_label = 'y')
p.line(source=src1,y='y',x='x',color='blue',line_width=2)
p.circle(source=src1,y='y',x='x',color='green')
columnsT = [TableColumn(field="mean", title="mean"),
TableColumn(field="std", title='std')]
data_table = DataTable(source=src2, columns=columnsT, width=400, height=400)
data_table.index_position = None
controls = WidgetBox(data_table)
layO = layout([[p],[controls]])
# Make a tab with the layout
tab1 = Panel(child=layO, title = 'test')
tabs = Tabs(tabs=[tab1])
show(tabs)
# Now the same plot, but fitted with a slider widget
def modify_doc(doc):
def make_dataset(N = 2):
data = pd.DataFrame(np.random.random([N,2]),columns=['x','y'])
dataMean = pd.DataFrame([],columns=['mean','std'])
dataMean.loc[:,'mean'] =data.mean()
dataMean.loc[:,'std'] =data.std()
return ColumnDataSource(data),ColumnDataSource(dataMean)
def make_plot(src):
# Blank plot with correct labels
p = figure(plot_width = 700, plot_height = 400,
title = 'Test case',x_axis_label = 'x', y_axis_label = 'y')
p.line(source=src,y='y',x='x',color='blue',line_width=2)
p.circle(source=src,y='y',x='x',color='green')
return p
def update(attr, old, new):
new_src, new_src2 = make_dataset(N_select.value)
src.data.update(new_src.data)
src2.data.update(new_src2.data)
N_select = Slider(start = 2, end = 20, step = 1, value = 2, title = 'number of points',width=700)
N_select.on_change('value', update)
columnsT = [
TableColumn(field="mean", title="mean"),
TableColumn(field="std", title='std')]
src, src2 = make_dataset(N_select.value)
data_table = DataTable(source=src2, columns=columnsT, width=400, height=400)
data_table.index_position = None
p = make_plot(src)
# Put controls in a single element
controls = WidgetBox(N_select,data_table)
layO = layout([[p],[controls]])
# Make a tab with the layout
tab1 = Panel(child=layO, title = 'test')
tabs = Tabs(tabs=[tab1])
doc.add_root(tabs)
handler= FunctionHandler(modify_doc)
app = Application(handler)
show(app)
如果我将output_notebook()更改为output_file('tryout.html'),则会出现以下错误,我无法理解,也无法找到解决方法:
运行时错误:没有为笔记本类型None安装显示挂钩
希望有人能帮我解决这个问题。
提前谢谢!
最佳答案
你所要求的是不可能的,至少我不理解你的问题。您已经创建了一个Bokeh服务器应用程序,其中包含真正的Python代码回调。独立的HTML文档不可能运行真正的Python代码,因为浏览器没有任何能力运行Python代码。真正的Python代码回调需要一个实时的、运行的Python解释器进程。当您在笔记本中嵌入bokeh服务器应用程序时,正如您在上面所做的,这个过程就是IPython内核。
如果你只是想要一个Bokeh服务器应用程序(需要在Bokeh服务器上运行,因为这是运行回调的Python进程),它可以在笔记本之外运行,最简单的方法是将所有代码放在一个脚本中
bokeh serve --show myapp.py
这些应用程序的大致轮廓是:
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Slider
from bokeh.plotting import figure
# create plots
plot = figure(...)
# create widgets
slider = Slider(...)
# add callbacks to widgets
def update(attr, old, new):
pass
slider.on_change('value', update)
# put things in a layout
layout = column(slider, plot)
# add to curdoc
curdoc().add_root(layout)
或者,也可以将Bokeh服务器应用程序嵌入到“常规”python脚本中。为此,请参见Embedding Bokeh Server as Library。
关于html - 将带有小部件的交互式散景图导出到独立HTML,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51989100/