神秘的散景气垫工具行为(多个框)

时间:2019-04-18 20:57:29

标签: python datetime bokeh

我有一些数据在某些地方缺少值。出于某种原因,仅在数据的最后一个中断之后将鼠标悬停在数据上,这与预期的一样,仅显示了一个悬停框。最后一个中断和倒数第二个之间的数据显示3个框。 (由于某些原因,屏幕截图没有捕获鼠标。在左图中,它位于曲线孔的左侧,在右图中-右侧。)将数据悬停在倒数第二个和最后一个之间产生5盒。依此类推...多余的框中的值不会随着光标的移动而变化,并且也都不同,并且这些框会移动并仅显示在最后一块数据中。 对这里发生的事情有任何想法吗?

我尝试做一个最小的例子,但是问题消失了……也许有人可以发现原始代码有什么问题?

import numpy as np
import pandas as pd
import warnings
from bokeh.layouts import widgetbox
from bokeh.plotting import figure, show, output_file, output_notebook
from bokeh.palettes import Spectral11, colorblind, Inferno, BuGn, brewer
from bokeh.models import HoverTool, value, LabelSet, Legend, ColumnDataSource, LinearColorMapper, BasicTicker, PrintfTickFormatter, ColorBar
from bokeh.models.widgets import DateRangeSlider, CheckboxButtonGroup
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.layouts import column, row
from json import loads
import ast

warnings.filterwarnings('ignore')


minD = data['Date'].values[0]
maxD = data['Date'].values[-1]


def datetime(x):
    return np.array(x, dtype=np.datetime64)


TOOLS = 'save,pan,box_zoom,reset,wheel_zoom'
p = figure(y_axis_type="linear",
           plot_height=400, tools=TOOLS, plot_width=1300,
           x_range=(minD, maxD), x_axis_type="datetime")

source = ColumnDataSource(data={
        'Date': datetime(data['Date']),
        'x': data['x'],
        'y': data['y'],
        'z': data['z']})

p.xaxis.axis_label = 'Date'
p.yaxis.axis_label = 'Position (m)'


def add_plot(y, color):
    new_plot = p.line(x='Date', y=y, line_width=1, color=color, source=source)
    return new_plot


x = add_plot('x', 'red')
y = add_plot('y', 'green')
z = add_plot('z', 'blue')

checkbox = CheckboxButtonGroup(labels=['x', 'y', 'z'], active=[0, 1, 2])
checkbox.callback = CustomJS(args=dict(x=x, y=y, z=z), code="""
    //console.log(cb_obj.active);
    x.visible = false;
    y.visible = false;
    z.visible = false;
    for (i in cb_obj.active) {
        //console.log(cb_obj.active[i]);
        if (cb_obj.active[i] == 0) {
            x.visible = true;
        } else if (cb_obj.active[i] == 1) {
            y.visible = true;
        } else if (cb_obj.active[i] == 2) {
            z.visible = true;
        }
    }
""")

callback = CustomJS(args=dict(p=p), code="""
    var a = cb_obj.value;
    p.x_range.start = a[0];
    p.x_range.end = a[1];
""")

start_date = pd.to_datetime(minD)
end_date = pd.to_datetime(maxD)
range_slider = DateRangeSlider(start=start_date, end=end_date,
                               value=(start_date, end_date), step=1)
range_slider.js_on_change('value', callback)


def get_hovertools():
    hovers = {'x': x, 'y': y, 'z': z}
    for k, v in hovers.items():
        hovers[k] = HoverTool(mode='vline', renderers=[v])
        hovers[k].tooltips = [('Date', '@Date{%F %H:%M:%S.%u}'),
                              (k, '@{'+k+'}{%0.2f}m')]
        hovers[k].formatters = {'Date': 'datetime', k: 'printf'}
        p.add_tools(hovers[k])


get_hovertools()

layout = column(p, widgetbox(checkbox), widgetbox(range_slider))

show(layout)

enter image description here

2 个答案:

答案 0 :(得分:1)

您在mode = 'vline'中使用了HoverTool,因此,如果线条很陡,在字形中可能会有许多点具有类似的y坐标,因此悬停将全部击中它们并显示多个框。将模式设置为mode = "mouse"应该有帮助

答案 1 :(得分:0)

原来我的一些日期是NaT ...真是奇怪,这就是它决定处理它们的方式,方法是仅在最后NaT ... bokeh之后的值上显示适当的悬停框让我感到困惑.....