2017-08-30 7 views
1

CheckButtonGroupを使用してbokeh serveプロットを作成しようとしています。私はsource.dataを更新することができますが、プロットは更新されません。私は間違って何をしていますか?source.dataはbokeh serveで更新されますが、プロットは変更されません。

実際には、私のコンピュータからデータセットをインポートしますが、今はpandasデータフレームの例を作成します。私は 'x'列(x軸の変数)と1つ以上の他の列(y軸の変数)を選択したいと思います。

import pandas as pd 
from bokeh.io import curdoc 
from bokeh.plotting import figure 
from bokeh.layouts import row, widgetbox 
from bokeh.models.widgets import CheckboxButtonGroup 
from bokeh.models import ColumnDataSource 

dataset = pd.DataFrame(columns=['x','y1','y2','y3']) 
dataset['x'] = [1, 2, 3, 4] 
dataset['y1'] = [10, 20, 30, 40] 
dataset['y2'] = [11, 21, 31, 41] 
dataset['y3'] = [12, 22, 32, 43] 

pos_cols = ['y1', 'y2', 'y3'] # possible column names 
col_list = ['y1', 'y2'] # default columns in plotted data 
use_data = dataset[col_list] 
use_data['x'] = dataset.loc[:, 'x'] 

source = ColumnDataSource(use_data) 

p = figure(
    tools="pan,box_zoom,wheel_zoom,reset,save", 
    x_axis_label='xtitle', y_axis_label='ytitle', 
    title="Simulations" 
) 

# make default plot with the two columns 
for column in col_list: 
    p.line('x', column, source=source) 

check = CheckboxButtonGroup(labels=["y1", "y2", "y3"], active=[0, 1]) # A check box for every column 

def update_lines(new): 

    col_list = [pos_cols[i] for i in new] 
    use_data = dataset[col_list] 
    use_data['x'] = dataset.loc[:, 'x'] 
    source.data = source.from_df(use_data) 

    print(source.data) # source.data is correctly updated, but does not seem to trigger a new plot 

check.on_click(update_lines) 

doc = curdoc() 
doc.add_root(row(check, p, width=800)) 
doc.title = "Simulations" 

私はtry.pyとしてコードを保存し、bokeh serve try.pyでWindowsのプロンプトから実行します。プロットはhttp://localhost:5006

答えて

0

で表示されます。'y3'のような列のグリフを作成していて、実際には列を送信しないことが問題です。'y3'を開始してください。 Bokehはそれを好きではありません(ブラウザのJSコンソールに存在しない列にアクセスしようとするとエラーメッセージが表示される)

より良いアプローチは、すべてのデータを不必要に再送信することではなく、グリフレンダラーの.visible属性。ここでは(それが目に見えるすべての行から始まりますが、あなたはそれを変えることができる)、最小限の例です。また

import pandas as pd 
from bokeh.io import curdoc 
from bokeh.plotting import figure 
from bokeh.layouts import row 
from bokeh.models import CheckboxButtonGroup, ColumnDataSource 

dataset = pd.DataFrame(columns=['x','y1','y2','y3']) 
dataset['x'] = [1, 2, 3, 4] 
dataset['y1'] = [10, 20, 30, 40] 
dataset['y2'] = [11, 21, 31, 41] 
dataset['y3'] = [12, 22, 32, 43] 

source = ColumnDataSource(data=dataset) 

p = figure() 

lines = [] 
for column in ['y1', 'y2', 'y3']: 
    lines.append(p.line('x', column, source=source)) 

check = CheckboxButtonGroup(labels=["y1", "y2", "y3"], active=[0, 1, 2]) 

def update_lines(new): 
    for i in [0, 1, 2]: 
     if i in new: 
      lines[i].visible = True 
     else: 
      lines[i].visible = False 

check.on_click(update_lines) 

doc = curdoc() 
doc.add_root(row(check, p, width=800)) 

、あなただけの行を非表示にしたり、ミュートすることができるように探している場合は、もっと簡単な方法がするだろうボケのインタラクティブ伝説に建てを使用します。

http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/legends.html#userguide-interaction-legends

+0

あなたは@bigreddotありがとうございます。これは良い解決策に思えます。しかし、プロットのユーザーにプロットするデータのスライスを指定させたい場合はどうすればいいでしょうか。例えば、私が4つのカラムを持っていて、どのカラムにx軸変数とy軸変数を指定するかを指定したいとします。それから私は開始プロットのすべてのデータを持たずに(データを更新することによって)プロットを更新できる必要があります。私はsource.dataを実際にプロットして更新する方法を知りたいですか? –

+0

新しいフィギュアを作成するだけです。例えば、 https://github.com/bokeh/bokeh/blob/master/examples/app/crossfilter/main.pyまた、データソース内の実際のデータを変更することもできます。私は確信している他の方法もあります。覚えておいていただきたいのは、「表示列 'foo'」と表示されているグリフの列「foo」が存在する必要があるということです。それが上記のあなたの問題でした。 – bigreddot

関連する問題