You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bokeh悬停工具能否实时运行Python代码生成交互式图表?

关于Bokeh悬停工具实时生成图表的解决方案

嘿,先直接给你答案:Bokeh的原生悬停工具没办法直接实时运行Python代码。原因很简单——Bokeh的前端交互(比如浏览器里的悬停)和后端Python代码是分开运行的,默认情况下,前端事件没法直接触发后端的Python函数执行。不过别担心,有两种更优的方案能解决你的需求,不用预生成上万张图表。

方案一:用Bokeh Server实现前后端联动

这是最贴合你需求的方案,因为Bokeh Server支持前后端双向通信,能让你在用户悬停时按需用Python生成小图表:

  1. 准备数据源:主图的均值数据之外,把每个数据点对应的区间原始数据也存在ColumnDataSource里(比如用一个列表字段,每个元素是该区间的时间和数值数组)。
  2. 监听悬停事件:在Bokeh Server中,给HoverTool绑定事件回调,当用户悬停在某个数据点上时,触发后端Python函数。
  3. 生成小图表:在Python回调里,取出当前点对应的区间原始数据,用Bokeh快速生成一个小型时间序列图,把它转换成HTML片段(或者用components()方法获取图表的JS和HTML)。
  4. 更新悬停提示:把生成的小图HTML插入到悬停提示的内容中,推送到前端展示。

举个简单的代码框架示例(核心逻辑):

from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.models.tools import CustomJS

# 主数据:均值
main_source = ColumnDataSource(data={
    'x': [1,2,3],
    'y': [5,7,6],
    # 每个点对应的区间原始数据
    'interval_data': [
        {'t': [1,2,3], 'v': [4,5,6]},
        {'t': [4,5,6], 'v': [6,7,8]},
        {'t': [7,8,9], 'v': [5,6,5]}
    ]
})

p = figure(plot_width=800, plot_height=400)
p.circle('x', 'y', size=15, source=main_source)

# 定义悬停提示的基础模板
hover = HoverTool(tooltips="""
    <div>
        <h4>区间均值: @y</h4>
        <div id="mini_plot_container"></div>
    </div>
""")
p.add_tools(hover)

# Bokeh Server的回调函数,处理悬停事件
def on_hover(event):
    if event.index is not None:
        # 获取当前点的区间数据
        interval_data = main_source.data['interval_data'][event.index]
        # 生成小图表
        mini_p = figure(plot_width=200, plot_height=150, toolbar_location=None)
        mini_p.line('t', 'v', source=ColumnDataSource(interval_data))
        # 把小图转换成HTML组件
        from bokeh.embed import components
        script, div = components(mini_p)
        # 更新前端的mini_plot_container内容
        curdoc().add_next_tick_callback(lambda: curdoc().session_context._session.send_message(
            {"type": "patch", "data": {"div": div, "script": script}}
        ))

# 绑定悬停事件
p.js_on_event('mousemove', CustomJS(args=dict(source=main_source), code="""
    // 触发后端Python回调
    if (cb_data.index.indices.length > 0) {
        Bokeh.documents[0].event_manager.trigger('hover', {index: cb_data.index.indices[0]})
    }
"""))

curdoc().add_root(p)

这个方案的优势是完全用Python生成小图,符合你的开发习惯,而且只有用户悬停时才生成对应的图表,不会预生成上万张,大大节省时间和资源。

方案二:前端JS动态生成小图表

如果不想用Bokeh Server,也可以把所有区间的原始数据提前传到前端,用JavaScript动态生成小图表:

  1. 把所有区间的原始数据存入ColumnDataSource,前端可以直接访问这些数据。
  2. 自定义HoverTool的HTML模板,在模板里加入一个空的容器,比如<div id="mini_plot"></div>。
  3. 用CustomJS绑定悬停事件,当用户悬停时,取出当前点的区间数据,用前端图表库(比如Bokeh的JS API、D3.js或者Chart.js)动态渲染小图到容器里。

这个方案不需要后端联动,纯前端处理,适合不需要复杂Python逻辑的场景,速度更快。

总结

不用纠结预生成上万张图表的方案,用Bokeh Server做前后端联动(推荐)或者前端JS动态渲染,都能实现“悬停时实时生成区间数据小图”的需求,而且效率高得多。

内容的提问来源于stack exchange,提问作者FChm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:31:54