Python Jupyter笔记本中的Bokeh绘图未更新

Python Jupyter笔记本中的Bokeh绘图未更新,python,jupyter-notebook,bokeh,python-interactive,Python,Jupyter Notebook,Bokeh,Python Interactive,我想要绘制一些具有多个特征的数据,并想要制作一个交互式2d绘图,用户可以在其中从特征列表中选择轴,以查看任意两个特征之间的关系。但是,在我的代码中,绘图不会根据用户输入进行更新 我用的是Jupyter笔记本,我试着用bokeh软件包来制作情节。我想坚持使用bokeh小部件,而不是iPython小部件。任何帮助都将不胜感激 下面是一些最简单的代码 import numpy as np import pandas as pd from bokeh.layouts import row, widget

我想要绘制一些具有多个特征的数据,并想要制作一个交互式2d绘图,用户可以在其中从特征列表中选择轴,以查看任意两个特征之间的关系。但是,在我的代码中,绘图不会根据用户输入进行更新

我用的是Jupyter笔记本,我试着用bokeh软件包来制作情节。我想坚持使用bokeh小部件,而不是iPython小部件。任何帮助都将不胜感激

下面是一些最简单的代码

import numpy as np
import pandas as pd
from bokeh.layouts import row, widgetbox
from bokeh.models import CustomJS, Slider, Select
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.io import push_notebook, output_notebook, curdoc
from bokeh.client import push_session
output_notebook()

#create sample pandaframe to work with, this will store the actual data
a = np.arange(50).reshape((5,10))
labels = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
val_a = pd.DataFrame(a, columns=labels )

# Here is a dict of some keys that I want to be able to pick from for plotting
axis_map = {
    "A": "A",
    "B": "B",
    "C": "C"
}

#This is to update during the callback
code = ''' var data = val_a;
           var val1 = x_axis.value;
           var val2 = y_axis.value;
           x = data['val1'];
           y = data['val2'];
           source.trigger('change');
           print x
            '''
source = ColumnDataSource(data=dict(x=[], y=[]))
callback = CustomJS(args=dict(source=source), code=code)

#Create two select widgets to pick the features of interest 
x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="A", callback = callback)
callback.args["val1"] = x_axis

y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="B", callback = callback)
callback.args["val2"] = y_axis

#plot the figures
plot = figure(plot_width=400, plot_height=400)
plot.circle(x= "x",y="y", source=source, line_width=3, line_alpha=0.6)


#update the plot
def update():
    x_name = axis_map[x_axis.value]
    y_name = axis_map[y_axis.value]

    plot.xaxis.axis_label = x_axis.value
    plot.yaxis.axis_label = y_axis.value
    print x_name
    print val_a[x_name]
    source.data = dict(
        x=val_a[x_name],
        y=val_a[y_name],

    )

controls = [ x_axis, y_axis]
for control in controls:
    control.on_change('value', lambda attr, old, new: update())


update()
push_notebook()

#Display the graph in a jupyter notebook
layout = row(plot, x_axis, y_axis)
show(layout, notebook_handle=True)

我认为,为了简化代码,您可以只使用JS回调或python回调,而无需同时使用这两种回调

要更改数据源,您需要将原始数据馈送到JS回调,然后在小部件中选择与所选值相对应的适当值

也可以在JS中以相同的方式设置轴标签。不确定这是否正是您想要的实现,但应该让您更接近

import numpy as np
import pandas as pd
from bokeh.layouts import row, widgetbox
from bokeh.models import CustomJS, Slider, Select
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.io import push_notebook, output_notebook, curdoc
from bokeh.client import push_session
output_notebook()

#create sample pandaframe to work with, this will store the actual data
a = np.arange(50).reshape((5,10))
labels = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
val_a = pd.DataFrame(a, columns=labels )

# Here is a dict of some keys that I want to be able to pick from for plotting
axis_map = {
    "A": "A",
    "B": "B",
    "C": "C"
}

#This is to update during the callback
code = ''' var data = source.data;
           var value1 = val1.value;
           var value2 = val2.value;
           var original_data = original_source.data
           // get data corresponding to selection
           x = original_data[value1];
           y = original_data[value2];
           data['x'] = x;
           data['y'] = y;
           source.trigger('change');
           // set axis labels
           x_axis.axis_label = value1
           y_axis.axis_label = value2
            '''
source = ColumnDataSource(data=dict(x=val_a['A'], y=val_a['B']))
original_source = ColumnDataSource(data=val_a.to_dict(orient='list'))


#plot the figures
plot = figure(plot_width=400, plot_height=400)
plot.circle(x= "x",y="y", source=source, line_width=3, line_alpha=0.6)


callback = CustomJS(args=dict(source=source, original_source = original_source, x_axis=plot.xaxis[0],y_axis=plot.yaxis[0]), code=code)

#Create two select widgets to pick the features of interest 
x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="A", callback = callback)
callback.args["val1"] = x_axis

y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="B", callback = callback)
callback.args["val2"] = y_axis

plot.xaxis[0].axis_label = 'A'
plot.yaxis[0].axis_label = 'B'

#Display the graph in a jupyter notebook
layout = row(plot, x_axis, y_axis)
show(layout, notebook_handle=True)