2017-01-20 14 views
2

Jupiter Notebook内のデータ領域をインタラクティブに選択するためにBokehを使用しようとしています。データが選択されると、ノートブック内の後続のセルでPythonを使用してさらに操作されます。bokehを使用してJupyter Notebook内のデータ領域を選択する

次のコードは、Jupyter Notebook内にプロットを生成します。 LassoSelectTool(または別の選択ツール)を使用して、ユーザはデータの領域を選択することができます。

import numpy as np 
from bokeh.plotting import figure, show 
from bokeh.io import output_notebook 
from bokeh.models import ColumnDataSource 
# Direct output to this notebook 
output_notebook() 

n = 100 
x = np.random.random(size=n) * 100 
y = np.random.random(size=n) * 100 
source = ColumnDataSource(data=dict(x=x, y=y)) 

figkwds = dict(plot_width=400, plot_height=300, webgl=True, 
      tools="pan,lasso_select,box_select,help", 
      active_drag="lasso_select") 

p1 = figure(**figkwds) 
p1.scatter('x', 'y', source=source, alpha=0.8) 

show(p1) 

次のJupyterセルで選択したデータにアクセスするにはどうすればよいですか?ドキュメントはCustomJSが選択と対話することを示唆していますが、私は他のBokehプロットを更新することしかできませんでした。私はより厳密な操作のために、選択されたデータをどのように図から外すかわかりません。

答えて

1

答えは、BokehのjavascriptからJupyterカーネルに戻るにはkernel.executeと表示されます。私はGithub issueに基づいて、次のコードを開発:http://nbviewer.jupyter.org/github/arkottke/notebooks/blob/0b9fc5bac0de573005c84f6c2493bb4da59a103f/bokeh_selector_example.ipynb

import numpy as np 
from bokeh.plotting import gridplot, figure, show 
from bokeh.io import output_notebook, push_notebook 
from bokeh.models import ColumnDataSource, CustomJS 
# Direct output to this notebook 
output_notebook() 

# Create some data 
n = 100 
source = ColumnDataSource(data=dict(
    x=np.random.random(size=n) * 100, 
    y=np.random.random(size=n) * 100) 
) 
model = ColumnDataSource(data=dict(
    x=[], 
    y_obs=[], 
    y_pred=[], 
)) 

# Create a callback with a kernel.execute to return to Jupyter 
source.callback = CustomJS(code=""" 
     // Define a callback to capture errors on the Python side 
     function callback(msg){ 
      console.log("Python callback returned unexpected message:", msg) 
     } 
     callbacks = {iopub: {output: callback}}; 

     // Select the data 
     var inds = cb_obj.selected['1d'].indices; 
     var d1 = cb_obj.data; 
     var x = [] 
     var y = [] 
     for (i = 0; i < inds.length; i++) { 
      x.push(d1['x'][inds[i]]) 
      y.push(d1['y'][inds[i]]) 
     } 

     // Generate a command to execute in Python    
     data = { 
      'x': x, 
      'y': y, 
     }   
     var data_str = JSON.stringify(data) 
     var cmd = "saved_selected(" + data_str + ")" 

     // Execute the command on the Python kernel 
     var kernel = IPython.notebook.kernel; 
     kernel.execute(cmd, callbacks, {silent : false}); 
""") 


selected = dict() 
def saved_selected(values): 
    x = np.array(values['x']) 
    y_obs = np.array(values['y']) 

    # Sort by increasing x 
    sorted_indices = x.argsort() 
    x = x[sorted_indices] 
    y_obs = y_obs[sorted_indices] 

    if len(x) > 2: 
     # Do a simple linear model 
     A = np.vstack([x, np.ones(len(x))]).T 
     m, c = np.linalg.lstsq(A, y_obs)[0] 
     y_pred = m * x + c 

     data = {'x': x, 'y_obs': y_obs, 'y_pred': y_pred} 
     model.data.update(data) 
     # Update the selected dict for further manipulation 
     selected.update(data) 
     # Update the drawing 
     push_notebook(handle=handle) 

figkwds = dict(plot_width=500, plot_height=300, # webgl=True, 
       x_axis_label='X', y_axis_label='Y', 
       tools="pan,lasso_select,box_select,reset,help") 

p1 = figure(active_drag="lasso_select", **figkwds) 
p1.scatter('x', 'y', source=source, alpha=0.8) 

p2 = figure(**figkwds, 
      x_axis_type='log', x_range=[1, 100], 
      y_axis_type='log', y_range=[1, 100]) 
p2.scatter('x', 'y', source=source, alpha=0.8) 

p3 = figure(plot_width=500, plot_height=300, # webgl=True, 
      x_axis_label='X', y_axis_label='Y', 
      tools="pan,reset,help") 
p3.scatter('x', 'y', source=source, alpha=0.6) 
p3.scatter('x', 'y_obs', source=model, alpha=0.8, color='red') 
p3.line('x', 'y_pred', source=model) 

layout = gridplot([[p1], [p2], [p3]]) 

handle = show(layout, notebook_handle=True) 

このコードは、ここでJupyterノートブックとして現在利用可能です

関連する問題