如何使用Bokeh更新NetworkX网络图的数据源并实现按钮触发更新?
如何在Bokeh Server中点击按钮更新网络图数据源
因为from_networkx确实不支持直接传入自定义的source参数,但我们可以通过更新GraphRenderer的节点/边数据源来实现动态更新,而不需要重新调用from_networkx生成新的渲染器。下面是具体的实现步骤和示例代码:
核心思路
from_networkx()返回的是GraphRenderer对象,它包含两个关键部分:
node_renderer.data_source:节点的数据源(ColumnDataSource类型)edge_renderer.data_source:边的数据源(ColumnDataSource类型)
我们只需要在按钮回调中,生成新的节点和边数据,直接替换这两个数据源的data属性,Bokeh Server就会自动更新视图。
完整示例代码
from bokeh.io import curdoc from bokeh.models import Button from bokeh.plotting import figure from bokeh.layouts import column import networkx as nx # 初始化初始网络图 def create_initial_graph(): G = nx.Graph() G.add_edges_from([(1, 2), (2, 3), (3, 1), (3, 4)]) return G # 创建绘图对象 plot = figure( title="Knowledge Graph", tools="box_select,pan,wheel_zoom,box_zoom,reset", toolbar_location="right", x_range=(-2.5, 2.5), y_range=(-2.5, 2.5) ) # 生成初始GraphRenderer并添加到绘图中 initial_G = create_initial_graph() graph_renderer = nx.from_networkx( initial_G, nx.spring_layout, # 使用spring布局 scale=2, center=(0, 0) ) plot.renderers.append(graph_renderer) # 定义更新网络图的回调函数 def update_graph(): # 1. 创建新的网络图数据 new_G = nx.Graph() new_G.add_edges_from([(1, 5), (5, 6), (6, 2), (2, 5), (4, 6)]) # 2. 为新图计算布局(如果需要保持布局可以跳过这步,直接复用旧坐标) new_pos = nx.spring_layout(new_G, scale=2, center=(0, 0)) # 3. 准备节点数据:必须包含'index'字段(对应节点ID),以及x/y坐标 node_data = { 'index': list(new_G.nodes()), 'x': [new_pos[node][0] for node in new_G.nodes()], 'y': [new_pos[node][1] for node in new_G.nodes()] } # 4. 准备边数据:需要'start'/'end'(对应节点ID),以及x0/y0(起点坐标)、x1/y1(终点坐标) edge_data = { 'start': [u for u, v in new_G.edges()], 'end': [v for u, v in new_G.edges()], 'x0': [new_pos[u][0] for u, v in new_G.edges()], 'y0': [new_pos[u][1] for u, v in new_G.edges()], 'x1': [new_pos[v][0] for u, v in new_G.edges()], 'y1': [new_pos[v][1] for u, v in new_G.edges()] } # 5. 更新数据源(关键!这一步会触发视图自动刷新) graph_renderer.node_renderer.data_source.data = node_data graph_renderer.edge_renderer.data_source.data = edge_data # 创建更新按钮并绑定回调 update_btn = Button(label="更新网络图", button_type="success") update_btn.on_click(update_graph) # 组装布局并添加到Bokeh Server文档中 curdoc().add_root(column(update_btn, plot))
关键注意事项
- 节点数据必须包含
index字段:GraphRenderer默认使用index字段来识别节点,所以新的节点数据里一定要包含这个字段,值对应节点的ID。 - 边数据的坐标匹配:边的
x0/y0要对应起点的坐标,x1/y1对应终点的坐标,否则边会显示错误。 - 布局复用选项:如果你希望更新数据源后保持节点的位置不变,可以跳过重新计算布局的步骤,直接复用旧的
graph_renderer.node_renderer.data_source.data中的x和y字段,只更新index和边的数据。
内容的提问来源于stack exchange,提问作者Ly Harriet Bui
相关产品推荐
相关产品推荐

