基于Bokeh为堆叠条形图添加UC列CheckboxGroup筛选功能
实现Bokeh CheckboxGroup更新堆叠水平条形图的方案
嘿,我来帮你搞定这个Bokeh的交互功能!其实核心就是用CheckboxGroup组件结合JavaScript回调(CustomJS)来动态过滤数据并更新图表,下面给你一步步的具体实现方法,包含完整代码示例:
核心思路
咱们需要:
- 用
CheckboxGroup创建航司选择控件 - 给图表的数据源绑定CustomJS回调,监听CheckboxGroup的选中变化
- 在回调里根据选中的航司过滤原始数据,更新图表的数据源,实现实时刷新
完整代码示例
from bokeh.io import show, save from bokeh.layouts import column from bokeh.models import ColumnDataSource, CheckboxGroup, CustomJS from bokeh.plotting import figure # ---------------------- 1. 模拟你的数据集(替换成你的真实数据) ---------------------- # 数据结构:UC_Month(月份)、carrier(航司)、dep_delayed_15min_count(延误数)、on_time_count(准点数量) data = { "UC_Month": ["Jan", "Jan", "Jan", "Jan", "Jan", "Feb", "Feb", "Feb", "Feb", "Feb"], "carrier": ["WN", "AA", "UA", "OO", "OA", "WN", "AA", "UA", "OO", "OA"], "dep_delayed_15min_count": [120, 90, 80, 60, 40, 130, 100, 75, 55, 35], "on_time_count": [480, 410, 320, 240, 160, 520, 450, 350, 260, 180] } original_source = ColumnDataSource(data) # ---------------------- 2. 准备初始显示的数据源(默认显示所有航司) ---------------------- months = list(set(data["UC_Month"])) carriers = ["WN", "AA", "UA", "OO", "OA"] # 构建初始堆叠数据 stack_data = {"UC_Month": months} for carrier in carriers: # 提取该航司的延误和准点数据 delayed = [d for m, c, d in zip(data["UC_Month"], data["carrier"], data["dep_delayed_15min_count"]) if c == carrier] on_time = [t for m, c, t in zip(data["UC_Month"], data["carrier"], data["on_time_count"]) if c == carrier] stack_data[f"{carrier}_delayed"] = delayed stack_data[f"{carrier}_on_time"] = on_time stack_source = ColumnDataSource(stack_data) # ---------------------- 3. 创建堆叠水平条形图 ---------------------- p = figure(y_range=months, height=400, width=800, title="Flight On-Time vs Delayed by Carrier") # 绘制堆叠水平条形:先画延误,再画准点 p.hbar_stack( stackers=[f"{c}_delayed" for c in carriers], y="UC_Month", height=0.8, color="#e45756", source=stack_source, legend_label=[f"{c} Delayed" for c in carriers] ) p.hbar_stack( stackers=[f"{c}_on_time" for c in carriers], y="UC_Month", height=0.8, color="#4c72b0", source=stack_source, legend_label=[f"{c} On Time" for c in carriers] ) p.yaxis.axis_label = "Month" p.xaxis.axis_label = "Number of Flights" p.legend.location = "top_right" p.legend.click_policy = "hide" # 可选:点击图例隐藏对应系列 # ---------------------- 4. 创建CheckboxGroup控件 ---------------------- checkbox = CheckboxGroup( labels=carriers, active=list(range(len(carriers))), # 默认全部选中 width=200 ) # ---------------------- 5. 编写CustomJS回调函数 ---------------------- callback = CustomJS(args=dict(original_source=original_source, stack_source=stack_source, checkbox=checkbox, carriers=carriers), code=""" // 获取选中的航司索引 const active_indices = checkbox.active; const selected_carriers = active_indices.map(i => carriers[i]); // 如果没有选中任何航司,默认选中全部 const target_carriers = selected_carriers.length > 0 ? selected_carriers : carriers; // 从原始数据中提取月份(保持顺序) const months = original_source.data.UC_Month.filter((m, idx) => idx % carriers.length === 0); // 初始化新的堆叠数据 const new_data = {UC_Month: months}; // 遍历每个选中的航司,提取对应的数据 target_carriers.forEach(carrier => { const delayed = []; const on_time = []; months.forEach(month => { // 找到该月份该航司的数据 const idx = original_source.data.UC_Month.indexOf(month) + carriers.indexOf(carrier); delayed.push(original_source.data.dep_delayed_15min_count[idx]); on_time.push(original_source.data.on_time_count[idx]); }); new_data[`${carrier}_delayed`] = delayed; new_data[`${carrier}_on_time`] = on_time; }); // 更新堆叠图的数据源 stack_source.data = new_data; """) # 给CheckboxGroup绑定回调 checkbox.js_on_change('active', callback) # ---------------------- 6. 布局并输出HTML ---------------------- layout = column(checkbox, p) # 保存为HTML文件 save(layout, filename="flight_delay_chart.html") # 或者直接在浏览器显示 # show(layout)
关键部分解释
数据源处理:
original_source存储原始的全量数据,方便回调里过滤stack_source是图表直接使用的数据源,结构适配堆叠条形图的要求
CheckboxGroup配置:
labels设置航司选项,active默认全部选中,符合初始显示所有数据的需求
CustomJS回调逻辑:
- 监听CheckboxGroup的
active属性变化(即选中状态改变) - 过滤出选中的航司,处理空选择的边界情况(默认选全部)
- 从原始数据中提取对应航司的准点/延误数据,重新构建堆叠图需要的数据源结构
- 更新
stack_source的数据,图表会自动刷新
- 监听CheckboxGroup的
堆叠图绘制:
- 用
hbar_stack方法快速创建水平堆叠条形,分别对应延误和准点数据,颜色区分明显
- 用
这样你运行代码后生成的HTML页面,就能通过勾选CheckboxGroup里的航司选项,实时更新堆叠条形图啦!
内容的提问来源于stack exchange,提问作者A2N15
相关产品推荐
相关产品推荐

