18

我有一个具有特定属性的节点图,我想用 Python 中的 networkx 绘制该图,其中有几个属性作为节点外节点的标签。

有人可以帮助我如何编写代码来实现这一目标吗?

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

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

4 回答 4

11

您可以访问“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>

在此处输入图像描述

于 2013-01-29T05:35:39.657 回答
11

除了 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字符串列表在哪里。

于 2016-09-19T11:52:57.397 回答
3

我喜欢创建一个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 默认设置直接放置在节点上,右侧的标签略微上移

于 2021-05-13T17:31:31.537 回答
1

NetworkX 的文档draw_networkx_labels还显示,您可以使用horizontalalignmentverticalalignment参数来获得一个简单的、开箱即用的解决方案,而无需手动轻推标签。

文档

  • Horizo​​ntalalignment ({'center', 'right', 'left'}) – 水平对齐(默认='center')

  • verticalalignment ({'center', 'top', 'bottom', 'baseline', 'center_baseline'}) – 垂直对齐(默认='center')

更方便的是,您可以将其与更高级别的 NetworkX 函数一起使用,例如nx.draw()或其中一个nx.draw_spectral(或其变体),因为这些高级函数参数接受关键字参数,而关键字参数又传递给其低级函数。

所以下面的代码是一个最小可行的代码,它可以满足你的要求,即将标签推到节点之外:

G = nx.DiGraph(name='Email Social Network')
nx.draw(G, arrowsize=3, verticalalignment='bottom')
# or:
nx.draw(G, arrowsize=3, verticalalignment='top')
plt.show()

结果verticalalignment如下图所示: 在此处输入图像描述

于 2021-01-19T15:37:59.793 回答