Python中的Networkx - 将节点属性作为标签绘制在节点外部

23 投票
4 回答
28383 浏览
提问于 2025-04-17 13:49

我有一个包含特定属性的节点图,我想用Python的networkx库来绘制这个图,并且希望节点的多个属性作为标签显示在节点外面。

有没有人能帮我写代码来实现这个目标?

我的代码中有一个循环,它会为防火墙列表(fwList)中的每个输入生成一个“interface_?”的属性。

for y in fwList:
    g.add_node(n, type='Firewall')
    print 'Firewall ' + str(n) + ' :' 
    for x in fwList[n]:
        g.node[n]['interface_'+str(i)] = x
        print 'Interface '+str(i)+' = '+g.node[n]['interface_'+str(i)]
        i+=1
    i=1
    n+=1

然后,我会像下面这样绘制节点和边:

pos=nx.spring_layout(g)
nx.draw_networkx_edges(g, pos)
nx.draw_networkx_nodes(g,pos,nodelist=[1,2,3],node_shape='d',node_color='red')

之后我还会扩展一些新的节点,给它们不同的形状和颜色。

我尝试过用下面的代码给单个属性加标签,但没有成功。

labels=dict((n,d['interface_1']) for n,d in g.nodes(data=True))

而且我不知道怎么把文本放在节点外面……

4 个回答

6

我想创建一个 nudge 函数,用来把布局稍微移动一下。

import networkx as nx
import matplotlib.pyplot as plt

def nudge(pos, x_shift, y_shift):
    return {n:(x + x_shift, y + y_shift) for n,(x,y) in pos.items()}

G = nx.Graph()
G.add_edge('a','b')
G.add_edge('b','c')
G.add_edge('a','c')

pos = nx.spring_layout(G)
pos_nodes = nudge(pos, 0, 0.1)                              # shift the layout

fig, ax = plt.subplots(1,2,figsize=(12,6))
nx.draw_networkx(G, pos=pos, ax=ax[0])                      # default labeling
nx.draw_networkx(G, pos=pos, with_labels=False, ax=ax[1])   # default nodes and edges
nx.draw_networkx_labels(G, pos=pos_nodes, ax=ax[1])         # nudged labels
ax[1].set_ylim(tuple(i*1.1 for i in ax[1].get_ylim()))      # expand plot to fit labels
plt.show()

两个图形表示,左右并排,展示了三个节点组成的三角形。左边的图是按照networkx的默认设置,标签直接放在节点上,而右边的图则是标签稍微向上移动了一点。

15

除了Aric的回答之外,pos这个字典里面的值包含了x, y坐标。所以你可以对它进行操作,下面是一个例子:

pos_higher = {}
y_off = 1  # offset on the y axis

for k, v in pos.items():
    pos_higher[k] = (v[0], v[1]+y_off)

然后用新的位置来绘制标签:

nx.draw_networkx_labels(G, pos_higher, labels)

这里的G是你的图形对象,而labels是一个字符串列表。

14

你可以在'pos'这个字典里找到节点的位置。所以你可以使用matplotlib这个工具,把文字放在你想要的地方。例如:

In [1]: import networkx as nx

In [2]: G=nx.path_graph(3)

In [3]: pos=nx.spring_layout(G)

In [4]: nx.draw(G,pos)

In [5]: x,y=pos[1]

In [6]: import matplotlib.pyplot as plt

In [7]: plt.text(x,y+0.1,s='some text', bbox=dict(facecolor='red', alpha=0.5),horizontalalignment='center')
Out[7]: <matplotlib.text.Text at 0x4f1e490>

在这里输入图片描述

撰写回答