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



我有一个python/bokeh应用程序,其中我显示多个个体的时间序列数据,每个个体的单独绘图。图以列形式排列。

假设我为每个人提供了 1 年来每小时分辨率的体温信息(只是一个虚构的例子)。我在 y 轴上绘制了每个温度与 x 轴上的时间。我将所有这些图存储在字典中。所以我有一个字典indind中的键是单独的名称,相应的值是散景.ploting 图形对象。然后,我使用column()来渲染图形。

我正在研究一些人,比如26人。因此,当我启动该应用程序时,我有一列包含 26 个图,可以一次比较很多。(请理解,这是一个虚构的例子,仅用于交流。我的项目要求我不在同一图中叠加所有个人的数据。我知道散景允许我们按照图例在图绘图中"静音"和"隐藏"图层,如果我以相同的图形绘制它们,但我不能这样做。

因此,我提供了一个包含所有个人名称的复选框组,以便用户可以选择他们现在想要查看的个人。我的用户可能希望同时检查任意数量的个人。它可以是 3 或 4 或 10。因此,我无法固定在列中排列的绘图数量。

在复选框组小部件中的用户选择时,我需要以交互方式隐藏或显示绘图。我认为应该有一些 CustomJS 方法可以做到这一点,但我不知道怎么做。我知道我们可以使用 Javascript 更改对象的可见性,如下所述:使用 JavaScript 显示/隐藏"div">

任何帮助将不胜感激。此外,如果您可以展示如何根据用户输入(可以是下面的示例中的文本输入)对绘图重新排序,这将非常有帮助。

这是一个最小的工作示例:

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 轴不会更新。这是一个更新的最小工作示例(包括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 + 'nn')
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"

最新更新