javascript - 在用户输入的 Bokeh 中隐藏绘图 - 自定义 JS?

标签 javascript python bokeh

我有一个 python/bokeh 应用程序,在其中显示多个个体的时间序列数据,每个个体的单独绘图。这些图布置在一列中。

假设我有一年内每个人每小时的体温信息(只是一个虚构的例子)。我在 y 轴上绘制了它们各自的温度,在 x 轴上绘制了时间。我将所有这些图存储在字典中。所以我有一个字典 ind ,其中 ind 中的键是单独的名称,相应的值是 bokeh.plotting 图形对象。然后,我使用column() 来渲染图形。

我正在查看许多个人,比如 26 个。因此,当我启动应用程序时,我有一列 26 个图,需要同时比较很多。 (请理解,这是一个虚构的示例,仅用于通信。我的项目要求我不要在同一图中覆盖所有个体的数据。我知道 Bokeh 允许我们在图例中“静音”和“隐藏”图层如果我要把它们绘制在同一个图中,但我不能这样做。)

因此,我提供了一个包含所有个人名称的 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 和最新版本的 Bokeh 。

更新:下面的御好烧的答案可以完成上述工作,但在稍微复杂的情况下,它是不够的。我认为对御好烧的答案进行一些补充就可以了。基本上,我对每个人都有两种不同的观察结果,另一种是体重。用户可以从下拉菜单中选择他们想要研究的观察结果。绘制的数据被 react 性地绑定(bind)到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"

最佳答案

实现了字符串排序的示例(仅当用户输入当前检查值的字符串时)

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"

关于javascript - 在用户输入的 Bokeh 中隐藏绘图 - 自定义 JS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43345806/

相关文章:

javascript - AngularJS toastr 在文件上传时显示警报两次而不是一次

python - 优化外键查询时遇到问题

python - 使用数据着色器绘制时间序列图

javascript - Bokeh:用于调整 x 轴范围的 CustomJS TextInput 回调

Python RAM写入和读取

javascript - 在 iframe 内设置 Bokeh 属性

javascript - 编辑器 : Remove selection and set cursor position at the end of selection

javascript - 如何获得 Javascript 正则表达式匹配的字符串的实际值?

javascript - 存储购物车数据的更好方法是什么?

python - Django ORM 中查询过期时间差