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

如何使用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))

关键注意事项

  1. 节点数据必须包含index字段:GraphRenderer默认使用index字段来识别节点,所以新的节点数据里一定要包含这个字段,值对应节点的ID。
  2. 边数据的坐标匹配:边的x0/y0要对应起点的坐标,x1/y1对应终点的坐标,否则边会显示错误。
  3. 布局复用选项:如果你希望更新数据源后保持节点的位置不变,可以跳过重新计算布局的步骤,直接复用旧的graph_renderer.node_renderer.data_source.data中的x和y字段,只更新index和边的数据。

内容的提问来源于stack exchange,提问作者Ly Harriet Bui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:38:24