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

如何在Bokeh multi_line图中隐藏单条线并实现单条线选择?

我来帮你搞定这个Bokeh的多线交互问题!你遇到的multi_line无法单独选线、大量p.line性能拉胯的情况很常见,咱们可以用数据源管理+JS回调的方式完美解决,既保留multi_line的高性能,又能实现单条线选择和隐藏功能。

完整实现代码
import pandas as pd
import numpy as np
from bokeh.palettes import Spectral11
from bokeh.plotting import figure, show, output_file
from bokeh.models import ColumnDataSource, TapTool, CustomJS, CheckboxGroup
from bokeh.layouts import column

output_file('multi_line_interactive.html')

# 生成完整测试数据
dates = pd.date_range(start='2023-01-01', periods=5)
toy_df = pd.DataFrame(data=np.random.rand(5,3), columns=('a', 'b', 'c'), index=dates)

# 构造multi_line专用的数据源,新增控制字段
xs = [toy_df.index.to_list()] * len(toy_df.columns)
ys = [toy_df[col].to_list() for col in toy_df.columns]
colors = Spectral11[:len(toy_df.columns)]

source = ColumnDataSource(data={
    'xs': xs,
    'ys': ys,
    'colors': colors,
    'visible': [True]*len(toy_df.columns),  # 控制线条是否显示
    'selected': [False]*len(toy_df.columns) # 控制线条是否被选中
})

# 创建绘图对象
p = figure(x_axis_type="datetime", title="Interactive Multi-Line Chart", width=800, height=400)

# 绘制multi_line,绑定动态样式和可见性
multi_line_renderer = p.multi_line(
    'xs', 'ys', source=source,
    line_color='colors',
    # 用selected字段动态切换线条宽度,区分选中状态
    line_width={'field': 'selected', 'transform': {'type': 'factor_cmap', 'factors': [True, False], 'palette': [4, 2]}},
    visible='visible'  # 绑定可见性控制字段
)

# 1. 实现单条线点击选择功能
tap_tool = TapTool(renderers=[multi_line_renderer], behavior='select')
p.add_tools(tap_tool)

# 自定义JS回调:点击时切换对应线条的选中状态
select_callback = CustomJS(args=dict(source=source), code="""
    const indices = source.selected.indices;
    const selected = source.data.selected;
    
    // 清空所有之前的选中状态
    for (let i=0; i<selected.length; i++) {
        selected[i] = false;
    }
    
    // 标记当前点击的线条为选中
    if (indices.length > 0) {
        selected[indices[0]] = true;
    }
    
    source.change.emit();
""")
source.selected.js_on_change('indices', select_callback)

# 2. 实现线条显示/隐藏功能
checkbox_group = CheckboxGroup(
    labels=toy_df.columns.tolist(),
    active=list(range(len(toy_df.columns))),  # 默认全部显示
    width=200
)

# 绑定CheckboxGroup的JS回调,更新visible字段
hide_callback = CustomJS(args=dict(source=source, checkbox=checkbox_group), code="""
    const visible = source.data.visible;
    const active = checkbox.active;
    
    // 先将所有线条设为隐藏
    for (let i=0; i<visible.length; i++) {
        visible[i] = false;
    }
    
    // 将选中的Checkbox对应的线条设为显示
    for (let i=0; i<active.length; i++) {
        visible[active[i]] = true;
    }
    
    source.change.emit();
""")
checkbox_group.js_on_change('active', hide_callback)

# 组合控件与图表并展示
show(column(checkbox_group, p))
关键功能说明
  • 高性能保障:全程使用multi_line渲染,Bokeh会批量处理线条的绘制逻辑,比几百条单独的p.line快数倍
  • 单条线选择:通过TapTool捕获点击事件,JS回调更新数据源的selected字段,再通过factor_cmap动态调整选中线条的宽度(你也可以改成颜色变化,比如把选中线条设为红色)
  • 线条隐藏/显示:CheckboxGroup的勾选状态直接关联数据源的visible字段,multi_line会自动根据该字段控制线条是否渲染,无需重绘整个图表
  • 可扩展性:如果后续需要添加更多交互(比如右键菜单、双击事件),只需在数据源中新增对应控制字段,再编写JS回调即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:54:22