2017-04-11 35 views
1

我有一個python/bokeh應用程序,我在其中顯示多個人的時間序列數據,爲每個人單獨繪圖。這些地塊被放置在一列中。隱藏在用戶輸入 - 自定義JS的散景的情節?

讓我們說,我已經爲每個人提供了關於他們的體溫在每個小時的分辨率爲1年(僅僅是一個虛構的例子)的信息。我將y軸上的溫度與x軸上的時間作圖。我把所有這些地塊存儲在一本字典中。所以我有一個字典ind,使得ind中的鍵是單個名稱,對應的值是bokeh.plotting圖形對象。然後,我使用column()來呈現數字。

我有很多個人,我在看,說26.因此,當我啓動應用程序時,我有一個26個地塊的列,這是一次很多比較。 (請理解,這是一個虛構的例子,僅用於溝通,我的項目要求我不覆蓋同一圖形中所有人的數據,我知道散景使我們能夠通過圖例在圖中「隱藏」和「隱藏」圖層如果我將他們繪製在同一個圖中,但我不能這麼做)。

因此,我提供了一個CheckboxGroup,其中包含所有單個名稱,以便用戶可以選擇他們想要查看的個人。我的用戶可能想要同時檢查任意數量的個人。它可能是3或4或10.因此,我無法確定我將在列中排列的地塊的數量。

用戶在CheckboxGroup小部件中的選擇,我需要交互地隱藏或顯示情節。我認爲應該有一些CustomJS的做法,但我不知道如何。我知道我們可以使用Javascript更改對象的可見性,如下所述:Show/hide 'div' using JavaScript

任何幫助將不勝感激。此外,如果您可以展示如何根據用戶輸入重新排列圖(這可能像下例中的TextInput一樣),這將非常有幫助。

這裏是一個最低工作例如:

import string 
import random 
from bokeh.plotting import figure 
from bokeh.layouts import layout, widgetbox, column 
from bokeh.models.widgets import CheckboxGroup, TextInput 
from bokeh.models import Range1d 
from bokeh.io import curdoc, show 

data= dict(zip(list(string.ascii_lowercase), [{"x": [i for i in range(8760)], "y": [random.uniform(35, 40) for x in range(8760)]} for i in range(26)])) 

checkbox = CheckboxGroup(labels=list(string.ascii_lowercase), active=[0, 1, 4, 7, 10]) 
order = TextInput(title="Arrange plots in order as in this string") 
ind = {} 
for f in list(string.ascii_lowercase): 
    ind[f] = figure(plot_width= 800, plot_height= 100, tools ='save, reset, resize') 
    ind[f].vbar(x= "x", source= data[f], width= 0.5, bottom= 0, top= "y") 
    ind[f].y_range= Range1d(start= 32, end= 43) 
    ind[f].title.text = f 

p = column(*ind.values()) 

inputs = widgetbox(*[order, checkbox], sizing_mode='fixed') 

l = layout([ 
      [inputs, p], 
      ], sizing_mode='fixed') 

show(p) 

curdoc().add_root(l) 
curdoc().title = "test" 

注:Python 3中和背景虛化的最新版本。

更新:御好燒的答案如上所述,但在稍微複雜的情況下,它是不夠的。我認爲御好燒的答案有一些補充可以做到。基本上,我對每個人都有兩種不同的觀察,另一種觀察,比如說,體重。用戶可以從下拉菜單中選擇他們想要研究的觀察結果。繪製的數據被動地綁定到一個Select小部件。在默認加載後使用複選框一段時間後,如果將選擇更改爲權重,某些個人的x軸不會更新。這裏是一個更新的最小工作示例(包括大阪燒的答案):

import string 
import random 
from bokeh.plotting import figure 
from bokeh.layouts import layout, widgetbox, column 
from bokeh.models.widgets import CheckboxGroup, TextInput, Select 
from bokeh.models import Range1d, ColumnDataSource 
from bokeh.io import curdoc, show 

data1= dict(zip(list(string.ascii_lowercase), [{"x": [i for i in range(8760)], "y": [random.uniform(35, 40) for x in range(8760)]} for i in range(26)])) 

data2= dict(zip(list(string.ascii_lowercase), [{"x": [i for i in range(870)], "y": [random.uniform(140, 200) for x in range(870)]} for i in range(26)])) 

select_data = Select(title= "Select dataset", value= "data1", options= ["data1", "data2"]) 

def data_update(attr, new, old): 
    for f in list(string.ascii_lowercase): 
     print(select_data.value + '\n\n') 
     data[f].data= dict(x= globals()[select_data.value][f]["x"], y= globals()[select_data.value][f]["y"]) 

data= {f: ColumnDataSource(data= dict(x= data1[f]["x"], y= data1[f]["y"])) for f in list(string.ascii_lowercase)} 

checkbox = CheckboxGroup(labels=list(string.ascii_lowercase), active=[0, 1, 4, 7, 10]) 
order = TextInput(title="Arrange plots in order as in this string") 
ind = {} 
for f in list(string.ascii_lowercase): 
    ind[f] = figure(plot_width= 800, plot_height= 100, tools ='save, reset, resize') 
    ind[f].vbar(x= "x", source= data[f], width= 0.5, bottom= 0, top= "y") 
    ind[f].y_range= Range1d(start= 32, end= 43) 
    ind[f].title.text = f 

p = column(*ind.values()) 

def checkboxchange(attr,new,old): 
    plots = [] 
    for aind in checkbox.active: 
     plots.append(ind[checkbox.labels[aind]]) 
    l.children[0].children[1].children = plots 

def orderchange(attr,new,old): 
    # check the checkbox 
    chval = [] 
    for aind in checkbox.active: 
     chval.append(checkbox.labels[aind]) 
    # change the order if all the values in the string are also plotted currently 
    plots=[] 
    orderlist = [order.value[i] for i in range(len(order.value))] 
    if(len(set(orderlist+chval)) == len(chval)): 
     for aind in orderlist: 
      plots.append(ind[aind]) 
     l.children[0].children[1].children = plots 

order.on_change('value', orderchange) 
checkbox.on_change('active', checkboxchange) 
select_data.on_change('value', data_update) 

inputs = widgetbox(*[select_data, order, checkbox], sizing_mode='fixed') 

l = layout([ 
      [inputs, p], 
      ], sizing_mode='fixed') 

#show(p) 
plots = [] 
for aind in checkbox.active: 
    plots.append(ind[checkbox.labels[aind]]) 

l.children[0].children[1].children = plots 

curdoc().add_root(l) 
curdoc().title = "test" 

回答

2

實現兩個字符串排序(僅當用戶輸入與值的字符串當前已籤)

import string 
import random 
from bokeh.plotting import figure 
from bokeh.layouts import layout, widgetbox, column 
from bokeh.models.widgets import CheckboxGroup, TextInput 
from bokeh.models import Range1d 
from bokeh.io import curdoc, show 

data= dict(zip(list(string.ascii_lowercase), [{"x": [i for i in range(8760)], "y": [random.uniform(35, 40) for x in range(8760)]} for i in range(26)])) 

checkbox = CheckboxGroup(labels=list(string.ascii_lowercase), active=[0, 1, 4, 7, 10]) 
order = TextInput(title="Arrange plots in order as in this string") 
ind = {} 
for f in list(string.ascii_lowercase): 
    ind[f] = figure(plot_width= 800, plot_height= 100, tools ='save, reset, resize') 
    ind[f].vbar(x= "x", source= data[f], width= 0.5, bottom= 0, top= "y") 
    ind[f].y_range= Range1d(start= 32, end= 43) 
    ind[f].title.text = f 

p = column(*ind.values()) 

def checkboxchange(attr,new,old): 
    plots = [] 
    for aind in checkbox.active: 
     plots.append(ind[checkbox.labels[aind]]) 
    l.children[0].children[1].children = plots 

def orderchange(attr,new,old): 
    # check the checkbox 
    chval = [] 
    for aind in checkbox.active: 
     chval.append(checkbox.labels[aind]) 
    # change the order if all the values in the string are also plotted currently  
    plots=[] 
    orderlist = [order.value[i] for i in range(len(order.value))] 
    if(len(set(orderlist+chval)) == len(chval)): 
     for aind in orderlist: 
      plots.append(ind[aind]) 
     l.children[0].children[1].children = plots 

order.on_change('value', orderchange)    
checkbox.on_change('active', checkboxchange) 

inputs = widgetbox(*[order, checkbox], sizing_mode='fixed') 

l = layout([ 
      [inputs, p], 
      ], sizing_mode='fixed') 

#show(p) 
plots = [] 
for aind in checkbox.active: 
    plots.append(ind[checkbox.labels[aind]]) 

l.children[0].children[1].children = plots 

curdoc().add_root(l) 
curdoc().title = "test" 
+0

感謝一個例子!你的答案有效,但我的問題稍微複雜一點。你能看看我的問題中的更新嗎? –

+0

好吧,堅持不懈地回答你的問題,所以你應該接受它。無論如何,我認爲你的改變仍然有效,由於數據量和情節數量的原因,它會變得相當滯後。也許有更好的解決方案,但它可能會變得更加複雜。當情節沒有加載,你等了很久還是他們只是凍結 – Anthonydouc

+0

抱歉,我忘記接受答案。我會盡力等待。 –