隐藏用户输入的散景图 - 自定义JS?

时间:2017-04-11 12:22:45

标签: javascript python bokeh

我有一个python / bokeh应用程序,其中我显示了一些个人的时间序列数据,每个人都有单独的情节。这些地块列在一列中。

让我们说,我对每个人都有关于他们体温的信息,每小时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"

NB:Python 3和最新版本的散景。

更新:Okonomiyaki的答案如下所述,但是在稍微复杂的情况下,这是不够的。我认为Okonomiyaki的答案会增加一些。基本上,我对每个人都有两个不同的观察结果,另一个是我们说的重量。用户可以从下拉菜单中选择他们想要研究的观察。绘制的数据被反应绑定到Select小部件。在默认加载后使用复选框一段时间后,如果我将选择更改为权重,则某些个人的x轴不会更新。这是一个更新的最低工作示例(包括Okonomiyaki的答案):

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"

1 个答案:

答案 0 :(得分: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"