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

如何在Bokeh的NetworkX图中设置节点网格状自定义布局?

问题描述

我想创建类似元素周期表的网格状矩形元素,同时部分元素需要像图节点那样相互连接。我尝试用Bokeh结合NetworkX创建图,但没法设置节点的静态位置,测试代码如下:

import networkx as nx
from bokeh.io import save, output_file, show
from bokeh.models import Rect, MultiLine, Plot
from bokeh.models import HoverTool
from bokeh.models.graphs import NodesAndLinkedEdges
from bokeh.plotting import from_networkx

# Create Graph with seperate adding edges
G = nx.MultiGraph()
G.add_edge(1, 2)
G.add_edge(2, 3)
G.add_node(4)

# Create Graph with edge_list
G = nx.MultiGraph()
edge_list = [(1,2), (2,3), (2,4), (1,3)]
G.add_edges_from(edge_list)
G.add_nodes_from((5,6,7,8,9,10))

# create plot
plot = Plot(width = 1200,height = 900)
plot.add_tools(HoverTool(tooltips=[("Index", "@index")]))

# create graph with spring_layout
network_graph = from_networkx(G, nx.spring_layout, scale=3.4, center=(0,0))

# nodes
# test with x=10 and y=10, to set custom position
network_graph.node_renderer.glyph = Rect(x=10,y=10,width=0.3, height=0.2, fill_color='skyblue')
network_graph.node_renderer.hover_glyph = Rect(width=0.3, height=0.2, fill_color='navy')

# edges
network_graph.edge_renderer.glyph = MultiLine(line_width=3, line_color="lightgray", line_alpha=1.0)
network_graph.edge_renderer.hover_glyph = MultiLine(line_width=5, line_color="darkblue", line_alpha=1.0)

network_graph.inspection_policy = NodesAndLinkedEdges()
plot.renderers.append(network_graph)

output_file("graph_test.html")
save(plot)
show(plot)

请问如何为NetworkX图中的节点设置自定义位置,使其像元素周期表示例那样排列?


解决方案

要实现节点的自定义网格布局,核心是手动指定每个节点的坐标,并替换掉自动布局算法,具体步骤如下:

  1. 定义节点位置字典
    创建一个字典,键是节点ID,值是对应的(x,y)坐标,按照周期表的网格规则排列,比如:

    # 自定义网格位置,示例按2行5列排列
    node_positions = {
        1: (0, 1), 2: (1, 1), 3: (2, 1), 4: (3, 1), 5: (4, 1),
        6: (0, 0), 7: (1, 0), 8: (2, 0), 9: (3, 0), 10: (4, 0)
    }
    
  2. 使用自定义布局替代自动布局
    调用from_networkx时,把布局函数换成这个字典(NetworkX支持直接传入位置字典作为布局):

    network_graph = from_networkx(G, node_positions, scale=1, center=(0,0))
    

    这里scale和center可以根据需要调整,让整体布局适配画布大小。

  3. 修正节点渲染器的坐标绑定
    之前直接把x=10,y=10写死是错误的,应该绑定数据源中的x和y字段(from_networkx会自动把位置存入节点数据源的x、y列):

    network_graph.node_renderer.glyph = Rect(x='x', y='y', width=0.8, height=0.8, fill_color='skyblue')
    

    调整width和height让节点更贴合网格。

修改后的完整代码

import networkx as nx
from bokeh.io import save, output_file, show
from bokeh.models import Rect, MultiLine, Plot, Range1d
from bokeh.models import HoverTool
from bokeh.models.graphs import NodesAndLinkedEdges
from bokeh.plotting import from_networkx

# 创建图结构
G = nx.MultiGraph()
edge_list = [(1,2), (2,3), (2,4), (1,3)]
G.add_edges_from(edge_list)
G.add_nodes_from((5,6,7,8,9,10))

# 定义自定义网格位置(模拟周期表布局)
node_positions = {
    1: (0, 1), 2: (1, 1), 3: (2, 1), 4: (3, 1), 5: (4, 1),
    6: (0, 0), 7: (1, 0), 8: (2, 0), 9: (3, 0), 10: (4, 0)
}

# 创建画布,设置坐标轴范围适配布局
plot = Plot(width=1200, height=900, x_range=Range1d(-1, 5), y_range=Range1d(-1, 2))
plot.add_tools(HoverTool(tooltips=[("节点索引", "@index")]))

# 使用自定义位置创建图
network_graph = from_networkx(G, node_positions, scale=1, center=(0,0))

# 配置节点样式
network_graph.node_renderer.glyph = Rect(x='x', y='y', width=0.8, height=0.8, fill_color='skyblue', line_color='black')
network_graph.node_renderer.hover_glyph = Rect(x='x', y='y', width=0.8, height=0.8, fill_color='navy', line_color='black')

# 配置边样式
network_graph.edge_renderer.glyph = MultiLine(line_width=3, line_color="lightgray", line_alpha=1.0)
network_graph.edge_renderer.hover_glyph = MultiLine(line_width=5, line_color="darkblue", line_alpha=1.0)

network_graph.inspection_policy = NodesAndLinkedEdges()
plot.renderers.append(network_graph)

output_file("periodic_graph.html")
save(plot)
show(plot)

关键说明

  • 自定义位置字典可以完全按照周期表的行列规则设计,比如给每个节点分配对应的周期(y轴)和族(x轴)坐标。
  • 画布的x_range和y_range需要根据自定义位置调整,确保所有节点都在可视范围内。
  • 节点的width和height可以根据网格密度调整,避免重叠。

内容的提问来源于stack exchange,提问作者scoda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:44:52