2016-06-26 25 views
3

私は探索したい大きなデータセットを持っています。しかし、私は複数のプロットを作成したくありません。私はちょうど私が対話的にx軸とy軸に使用されている列を変更することができる単一のプロットが必要なので、プロット自体が更新されます。プロットされる列を対話的に変更するBokeh

私はBokehを使ってPython/Bokehでこのスクリプトをブラウザに提供しようとしています。しかし、私はプロットを更新する方法を明確にしていません。基になるデータソースが変更された例がたくさんありますが、これをやりたくないのですが、どの列がプロットされているかを変更したいだけです。

ここでは、私が以下にしたいことを簡単に説明しました。これは、データソースのxとyの列を選択するための2つの '選択'ウィジェットを使用します。これらには、 'Line'グリフが参照している列を変更しようとするコールバックがあります。しかし、これは動作していないようです。アドバイスは大歓迎です。

import numpy as np 

from bokeh.models import ColumnDataSource 
from bokeh.plotting import Figure 

from bokeh.models.widgets import Select,TextInput 
from bokeh.models.glyphs import Line 
from bokeh.models.layouts import HBox, VBox 
from bokeh.io import curdoc 


#============================================================================== 
#%% Define some Data 
#============================================================================== 
N = 200 

# Define the data to be used 
x = np.linspace(0,4.*np.pi,N) 
y = 3*np.cos(2*np.pi*x + np.pi*0.2) 
z = 0.5*np.sin(2*np.pi*0.8*x + np.pi*0.4) 

source = ColumnDataSource({'x':x,'cos':y,'sin':z}) 


#============================================================================== 
#%% Layout 
#============================================================================== 


TOOLS = "box_select,lasso_select,help" 

# create a new plot 
plot = Figure(tools=TOOLS, title=None) 

# Make a line and connect to data source 
glyph = Line(x="x", y="cos", line_color="#F46D43", line_width=6, line_alpha=0.6) 
plot.add_glyph(source, glyph) 

# Add list boxes for selecting which columns to plot on the x and y axis 
yaxis_select = Select(title="Y axis:", value="cos", 
          options=['x','cos','sin']) 


xaxis_select = Select(title="X axis:", value="x", 
          options=['x','cos','sin']) 


# Text input as a title 
text = TextInput(title="title", value='my sine wave plotter') 

# Layout widgets next to the plot      
controls = VBox(text,yaxis_select,xaxis_select) 

layout = HBox(controls,plot,width=800) 


#============================================================================== 
#%% Callbacks 
#============================================================================== 
# Put callbacks on the list boxes so that when they are changed the columns being 
# plotted get changed. 

def update_x_axis(attr, old, new): 
    # Change the column used for the x axis 
    glyph.x = xaxis_select.value 


def update_y_axis(attr, old, new): 
    # Change the column used for the y axis 
    glyph.y = yaxis_select.value 



yaxis_select.on_change('value', update_y_axis) 
xaxis_select.on_change('value', update_x_axis) 



#============================================================================== 
#%% Add to document root 
#============================================================================== 

curdoc().add_root(layout) 
curdoc().title = "Plotting app" 

答えて

3

次のスクリプトはうまくいくようです。代わりにBokeh ServerではなくCustomJSクライアントサイドスタイルを使用します。

import numpy as np 

from bokeh.models import ColumnDataSource 
from bokeh.plotting import Figure 

from bokeh.models.widgets import Select,TextInput 
from bokeh.models.layouts import HBox, VBox 
import bokeh.io 
from bokeh.models import CustomJS 

N = 200 

# Define the data to be used 
x = np.linspace(0,4.*np.pi,N) 
y = 3*np.cos(2*np.pi*x + np.pi*0.2) 
z = 0.5*np.sin(2*np.pi*0.8*x + np.pi*0.4) 

source = ColumnDataSource(data={'x':x,'y':y, 'X': x, 'cos':y,'sin':z}) 


code=""" 
     var data = source.get('data'); 
     var r = data[cb_obj.get('value')]; 
     var {var} = data[cb_obj.get('value')]; 
     //window.alert("{var} " + cb_obj.get('value') + {var} ); 
     for (i = 0; i < r.length; i++) {{ 
      {var}[i] = r[i] ; 
      data['{var}'][i] = r[i]; 
     }} 
     source.trigger('change'); 
    """ 

callbackx = CustomJS(args=dict(source=source), code=code.format(var="x")) 
callbacky = CustomJS(args=dict(source=source), code=code.format(var="y")) 

# create a new plot 
plot = Figure(title=None) 

# Make a line and connect to data source 
plot.line(x="x", y="y", line_color="#F46D43", line_width=6, line_alpha=0.6, source=source) 


# Add list boxes for selecting which columns to plot on the x and y axis 
yaxis_select = Select(title="Y axis:", value="cos", 
          options=['X','cos','sin'], callback=callbacky) 


xaxis_select = Select(title="X axis:", value="x", 
          options=['X','cos','sin'], callback=callbackx) 


# Text input as a title 
text = TextInput(title="title", value='my sine wave plotter') 

# Layout widgets next to the plot      
controls = VBox(text,yaxis_select,xaxis_select) 

layout = HBox(controls,plot,width=800) 

bokeh.io.show(layout) 

しかし、私はそれができるようになるまでそれを一緒に微調整しました。そして私はなぜCustomJSコードの部分が複雑である必要があるのか​​分かりません。

特にJSパーツのfor-loop内の両方の行が実際に必要であると思われますが、同じことをしているようです。

私は誰かが実際に説明できるものを考え出すまで、この質問を答えません。

+0

私は期待していたものの

残念ながら、私は、これらの特定のフィールドを編集するための、完全にPythonの解決策を得ることができなかったことを私は「wouldn Javascriptで手を汚す必要があります。可能であれば、私はPythonにとどまることを好むでしょう。しかしこれはうまくいくと思われ、私をロード・ブロックに乗せます。ありがとう。 – Redlegjed

2

グリフが座標を取る実際のソースフィールドを編集するには、this questionにあるコードのバリエーションが必要です。 ImportanceOfBeingErnestのコードの改正は、Selectウィジェットから任意のキーを元ColumnDataSourceを変更したり、非表示にする必要なしに、正しい結果が得られます。私は明確にするためのコードの文字列を分離

import numpy as np 

from bokeh.models import ColumnDataSource 
from bokeh.plotting import Figure 

from bokeh.models.widgets import Select, TextInput 
from bokeh.models.layouts import HBox, VBox 
import bokeh.io 
from bokeh.io import curdoc 
from bokeh.models import CustomJS 

N = 200 

# Define the data to be used 
x = np.linspace(0, 4. * np.pi, N) 
y = 3 * np.cos(2 * np.pi * x + np.pi * 0.2) 
z = 0.5 * np.sin(2 * np.pi * 0.8 * x + np.pi * 0.4) 

data = {'x': x, 'cos': y, 'sin': z} 
source = ColumnDataSource(data=data) 

codex = """ 
      var column = cb_obj.value; 
      line1.glyph.x.field = column; 
      source.trigger('change') 
     """ 
codey = """ 
      var column = cb_obj.value; 
      line1.glyph.y.field = column; 
      source.trigger('change') 
     """ 

# create a new plot 
plot = Figure(title=None) 

# Make a line and connect to data source 
line1 = plot.line(x="x", y="cos", line_color="#F46D43", line_width=6, line_alpha=0.6, source=source) 

callbackx = CustomJS(args=dict(line1=line1, source=source), code=codex) 
callbacky = CustomJS(args=dict(line1=line1, source=source), code=codey) 

# Add list boxes for selecting which columns to plot on the x and y axis 
yaxis_select = Select(title="Y axis:", value="cos", 
         options=data.keys(), 
         callback=callbacky 
        ) 

xaxis_select = Select(title="X axis:", value="x", 
         options=data.keys(), 
         callback=callbackx 
        ) 

# Text input as a title 
text = TextInput(title="title", value='my sine wave plotter') 

# Layout widgets next to the plot 
controls = VBox(text, yaxis_select, xaxis_select) 

layout = HBox(controls, plot, width=800) 

# bokeh.io.show(layout) 
curdoc().add_root(layout) 
curdoc().title = "Sliders" 

が、ImportanceOfBeingErnestのString.Formatの()の使用でしたかなりきちんとした。 ImportanceOfBeingErnestのソリューションはが実際にすべてではJavaScriptを必要としません(ただし、データソースを変更し)

関連する問題