Bokeh绘制网络图时Select组件js_on_change事件无响应如何解决
问题根因
你当前的实现存在3个核心问题导致切换选择无效果:
- 你自行创建的
source和网络图实际渲染使用的数据源没有关联:from_networkx生成的渲染对象中,network_graph.edge_renderer.data_source才是负责边渲染的有效数据源,修改你自定义的source不会触达渲染层 - 切换选择的回调逻辑只修改了weight字段值,没有执行「过滤weight>0的边」的核心逻辑
- 初始化建图时仅传入了过滤后的边数据,JS侧没有全量边数据可用于切换后重新计算
修复后可运行代码
import networkx as nx import pandas as pd from bokeh.plotting import from_networkx, figure, show from bokeh.models import Range1d, MultiLine, HoverTool, CustomJS, Select, Column # 生成测试数据 d = {'weight': [1, 2,3,1,2], 'var': ["var1","var1","var1","var2", "var2"], 'source': ["a", "b","c","e","f"], 'target': ["c","g","e","a","h"]} df1 = pd.DataFrame(data=d) df2 = df1.pivot(index= ["source","target"], values = "weight", columns = "var").reset_index() df2 = df2.fillna(0) # 基础绘图配置 HOVER_TOOLTIPS = [("Search Term", "@index")] title = "my title" plot = figure(tooltips = HOVER_TOOLTIPS, tools="pan,wheel_zoom", active_scroll='wheel_zoom', x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=title, plot_width=1000 ) category_default = "var1" unique_categories = ["var1","var2"] # 初始化用过滤后的数据建图 init_df = df2[df2[category_default] > 0][["source", "target", category_default]].rename(columns={category_default: "weight"}) G = nx.from_pandas_edgelist(init_df, edge_attr = "weight") network_graph = from_networkx(G, nx.spring_layout, scale=10, center=(0, 0)) network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width="weight") plot.renderers.append(network_graph) # 下拉控件配置 select = Select(title='Category Selection', value=category_default, options=unique_categories) # 回调逻辑:传入全量数据和网络图的边数据源 callback = CustomJS( args={ "all_edges": df2.to_dict("list"), "edge_source": network_graph.edge_renderer.data_source }, code=""" const selected_var = cb_obj.value; const sources = all_edges.source; const targets = all_edges.target; const weights = all_edges[selected_var]; // 过滤weight>0的边 const new_sources = []; const new_targets = []; const new_weights = []; for (let i = 0; i < sources.length; i++) { if (weights[i] > 0) { new_sources.push(sources[i]); new_targets.push(targets[i]); new_weights.push(weights[i]); } } // 更新边数据源 edge_source.data = { 'start': new_sources, 'end': new_targets, 'weight': new_weights }; edge_source.change.emit(); """ ) select.js_on_change("value", callback) show(Column(plot, select))
内容的提问来源于stack exchange,提问作者linacarrillo
相关产品推荐
相关产品推荐

