神秘的bokeh hovertool行为(多个框)

2024-04-24 03:28:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些数据在某些地方丢失了值。由于某些原因,在数据的最后一次中断之后,仅在数据上悬停显示一个悬停框,如预期的那样。最后一次中断和倒数第二次之间的数据显示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


Tags: 数据fromimportobjdatadatetimedateplot
2条回答

原来我的一些约会对象是NaT。。。很奇怪,它决定这样处理它们,只在最后一个NaT之后的值上显示适当的悬停框。。。博基把我难住了。。。。。你知道吗

您在HoverTool中使用mode = 'vline',因此如果直线非常陡峭,则图示符中可能有许多点具有相似的y坐标,因此悬停将全部命中并显示多个框。将模式设置为mode = "mouse"应该会有所帮助

相关问题 更多 >