2017-08-30 49 views
1

我試圖讓背景虛化服務的情節與CheckButtonGroup。我設法更新我的source.data,但情節沒有得到更新。我究竟做錯了什麼?source.data更新情節不會改變

在現實中,我輸入的數據集從我的電腦,但現在我將創建一個例子大熊貓數據幀。我想選擇'x'列(作爲x軸變量)和一個或多個其他列(作爲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從窗口提示符運行它。該圖是可見的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。這看起來不錯。但是,如果我希望繪圖的用戶指定要繪製哪一部分數據,該怎麼辦。例如,當我有四列時,我希望它們指定哪個應該是x軸變量,哪個應該是y軸變量。然後,我需要能夠更新繪圖(通過更新數據),而不必在開始繪製所有數據。我想知道如何讓source.data更新在劇情中實際完成其工作? –

+0

一種選擇是簡單地創建一個新數字。見例如https://github.com/bokeh/bokeh/blob/master/examples/app/crossfilter/main.py或者,您可以更改數據源中的實際數據。我確信還有其他的方式。唯一要記住的是,如果你的字形表示「display column'foo'」,那麼列「foo」需要存在。那是你上面的問題。 – bigreddot