2017-05-26 11 views
0

Ich möchte einige Daten plotten, die mehrere Features hat, und möchte ein interaktives 2D-Diagramm erstellen, wo der Benutzer die Achse aus einer Liste von Features auswählen kann, um zu sehen, wie zwei Features zusammenhängen . In dem Code, den ich habe, wird das Diagramm jedoch nicht basierend auf Benutzereingaben aktualisiert.Bokeh Plot in Jupyter Notebook nicht aktualisiert

Ich benutze Jupyter Notebook, und versuche, die Plots mit dem Bokeh-Paket zu tun. Ich möchte lieber Bokeh-Widgets als iPython-Widgets verwenden. Jede Hilfe würde sehr geschätzt werden. Hier

ist einige minimale Code

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) 

Antwort

1

Ich denke, Ihren Code zu vereinfachen, können Sie nur Stick mit entweder einem JS Rückruf oder einem Python-Callback, keine Notwendigkeit für beide.

Um die Datenquelle zu ändern, müssen Sie die ursprünglichen Daten dem JS-Callback einspeisen und dann die entsprechenden Werte für den ausgewählten Wert in den Widgets auswählen.

Sie können die Achsenbeschriftungen auch in JS auf identische Weise festlegen. Nicht sicher, ob dies genau Ihre gewünschte Implementierung ist, aber sollte Sie viel näher bringen.

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) 
Verwandte Themen