Bokeh饼图如何通过js_on_change实现复选框控制动态筛选重绘
问题解决说明
你代码的核心问题有3个:
- 没有把饼图绑定的ColumnDataSource传给CustomJS回调,回调修改的数据和饼图渲染用的数据源完全无关
- 回调仅生成了选中的水果字典,没有重新计算饼图需要的角度、百分比字段,也没有把新数据同步给数据源
- Bokeh仅会在ColumnDataSource的
data属性发生变更时触发图形重绘,你之前的操作没有触发这个更新机制
完整可运行修改代码
from bokeh.layouts import column from bokeh.models import ColumnDataSource, CustomJS, CheckboxGroup from math import pi import pandas as pd from bokeh.io import show from bokeh.plotting import figure from bokeh.transform import cumsum from bokeh.palettes import Category10 # 原始数据 fruits = {'Apple': 10, 'Mango': 24, 'Graphes': 9, 'Banana': 15, 'Peach': 6, 'Pinapple' : 7, } fruit_list = list(fruits.keys()) color_list = Category10[len(fruits)] # 初始化数据源,显式创建ColumnDataSource方便后续传入回调 data = pd.Series(fruits).reset_index(name='value').rename(columns={'index':'Fruits'}) data['angle'] = data['value']/data['value'].sum() * 2 * pi data['color'] = color_list data['percent'] = data['value']/sum(fruits.values()) * 100 source = ColumnDataSource(data) # 绘制饼图 p = figure(plot_height=350, title='Pie chart', tools="hover", tooltips="@Fruits: @value : @percent{0.2f} %", x_range=(-0.5,1.0)) p.wedge(x=0, y=1, radius=0.4, start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'), line_color="white", fill_color='color', legend='Fruits', source=source) p.axis.axis_label = None p.axis.visible = False p.grid.grid_line_color = None # 交互回调 callback = CustomJS(args = {'source':source, 'fruit_list':fruit_list, 'color_list':color_list, 'raw_fruits':fruits}, code=""" const active = cb_obj.active; // 初始化各字段数组 let Fruits = [], value = [], color = [], angle = [], percent = []; let total = 0; // 第一步:收集选中的水果和对应数值,先算总和 active.forEach(idx => { let fruit = fruit_list[idx]; Fruits.push(fruit); let val = raw_fruits[fruit]; value.push(val); color.push(color_list[idx]); total += val; }) // 第二步:计算每个水果的角度和百分比 let current_angle = 0; value.forEach(val => { let ang = val / total * 2 * Math.PI; angle.push(ang); percent.push(val / total * 100); }) // 第三步:更新数据源,触发重绘 source.data = { Fruits: Fruits, value: value, color: color, angle: angle, percent: percent } """ ) # 复选框 checkbox_group = CheckboxGroup(labels=fruit_list, active = [0,1,2,3,4,5]) checkbox_group.js_on_change('active', callback) layout = column(checkbox_group, p) show(layout)
内容的提问来源于stack exchange,提问作者vinay tiwari
相关产品推荐
相关产品推荐

