散景和自定义JS-使用滑块更新多线图

时间:2019-02-18 14:36:57

标签: javascript python bokeh

我正在使用Bokeh生成交互式时间序列图。 可以同时显示n个系列。每个系列将显示从t = 0到t = x的值,其中x是滑块创建的值。

我正在使用ColumnDataSource包含所有内容,使用MultiLine字形显示系列,使用Slider进行滑块,并使用CustomJS来控制更新交互。

from bokeh.models import CustomJS, ColumnDataSource, Slider, Plot
from bokeh.models.glyph import MultiLine
from bokeh.io import show
from bokeh.layouts import column

data_dict = {'lons':[[-1.0, -1.1, -1.2, -1.3, -1.4], [-1.0, -1.1, -1.25, -1.35, -1.45]], 'lats':[[53.0, 53.1, 53.2, 53.3, 53.4], [53.05, 53.15, 53.25, 53.35, 53.45]]}

source = ColumnDataSource(data_dict)
p = Plot(title = None, plot_width = 400, plot_height = 400)
glyph = MultiLine(xs = 'lons', ys = 'lats')
p.add_glyph(source, glyph)

callback = CustomJS(args = dict(source = source), code = """
    var data = source.data;
    var time = time.value;
    var lons = data['lons']
    var lats = data['lats']
    var runners = lons.length()
    var new_lons = []
    var new_lats = []

    for(i=0; i<runners; i++{
        var runner_lons = lons[i].slice(0, time)
        var runner_lats = lats[i].slice(0, time)
        new_lons.push(runner_lons)
        new_lats.push(runner_lats)
    }
    lons = new_lons
    lats = new_lats

    source.change.emit();
    """)

slider = Slider(start = 0, , end = 5, value = 0, step = 1, callback = callback)
layout = column(p, slider)
callback.args["time"] = slider

show(layout)

此代码呈现图形,绘制的两条线都覆盖source.data中的所有点。

移动滑块将按预期更新lonslats中的数据,但是图形显示不会更新。

非常感谢收到的指针,建议,建议,解释!

3 个答案:

答案 0 :(得分:0)

我相信您正在寻找的内容已包含在文档中-请参阅:https://hub.mybinder.org/user/bokeh-bokeh-notebooks-ykp39727/notebooks/tutorial/06%20-%20Linking%20and%20Interactions.ipynb#Slider-widget-example

具体来说,类似以下的slider.js_on_change('value', calback)

答案 1 :(得分:0)

您的javascript代码中存在一些小问题(您忘记了),并且忘记了将带有新lons / lats的列表分配给源代码。),Slider中的语法错误以及进口。

#!/usr/bin/python3
from bokeh.models import CustomJS, ColumnDataSource, Slider, Plot
from bokeh.models.glyphs import MultiLine
from bokeh.io import show
from bokeh.layouts import column

data_dict = {'lons':[[-1.0, -1.1, -1.2, -1.3, -1.4], [-1.0, -1.1, -1.25, -1.35, -1.45]], 'lats':[[53.0, 53.1, 53.2, 53.3, 53.4], [53.05, 53.15, 53.25, 53.35, 53.45]]}

source = ColumnDataSource(data_dict)
p = Plot(title = None, plot_width = 400, plot_height = 400)
glyph = MultiLine(xs = 'lons', ys = 'lats')
p.add_glyph(source, glyph)

callback = CustomJS(args = dict(source = source), code = """
    var data = source.data;
    var time = time.value;
    var lons = data['lons']
    var lats = data['lats']
    var runners = lons.length
    var new_lons = []
    var new_lats = []

    for(i=0; i<runners; i++){
        var runner_lons = lons[i].slice(0, time)
        var runner_lats = lats[i].slice(0, time)
        new_lons.push(runner_lons)
        new_lats.push(runner_lats)
    }
    lons = new_lons
    lats = new_lats
    source.attributes.data.lons = new_lons
    source.attributes.data.lons = new_lats
    source.change.emit();
    """)

slider = Slider(start = 0, end = 5, value = 0, step = 1, callback = callback)
layout = column(p, slider)
callback.args["time"] = slider

show(layout)

答案 2 :(得分:0)

其他答案均部分正确,但不完整或存在各种问题。主要缺少的部分是,如果您每次滑动滑块时都对原始数据源进行切片,然后在第一个滑块移动之后进行切片,那么您现在将不再对原始数据进行切片,因此将无法正常工作。您需要单独发送完整的原始数据,并始终从原始数据中复制所需的子部分。这是一个完整的工作脚本:

figure

我已经更新了代码,以使用bokeh.plotting中的output$Table1 <- renderTable(data.frame(Shape = c("\u25CF", "\u25B2", "\u25FC", ""), "Genes" = c(input$custom_genes1, "Mean"), Analysed_values = c(t(analysis1()), mean(analysis1()))), striped = TRUE, bordered = TRUE, hover = TRUE) 来简化代码,并获取默认坐标轴等。还值得注意的是,滑块值0可能没有意义,带有该图的图将(正确)为空。