使用 matplotlib 在 networkx 中平方节点

问题描述

在开始之前,我要指出这个问题似乎是 this one 的重复,但这里的解决方案根本无法在 python3 中使用当前版本的 networkx 进行编译。该集合不会构造自身等。

所以我有一个 networkx 图,我使用 matplotlib 绘制。这是它的代码

class Vert:
  
    # default constructor
    def __init__(self,name,size,edges):
        self.name = name
        self.size = size
        self.edges = edges


import networkx as nx
import matplotlib.pyplot as plt

nodes = []
nodes.append(Vert('A',1,['B','C']))
nodes.append(Vert('B',3,['D']))
nodes.append(Vert('C',4,['D']))
nodes.append(Vert('D',7,[]))
nodes.append(Vert('Y',64,[]))

G = nx.DiGraph()
for v  in nodes:
    G.add_node(v.name,s='v')
    for e in v.edges:
        G.add_edge(v.name,e)

node_sizes = [V.size * 100 for V in nodes]
shapes = set((aShape[1]["s"] for aShape in G.nodes(data = True)))

nx.draw(G,font_weight='bold',with_labels = True,node_size=node_sizes,node_shape= shapes)

#plt.savefig('plot.png',bBox_inches='tight')
plt.show()

我需要一些节点具有方形或三角形形状,我该怎么做?

解决方法

旧答案中的代码无法运行,因为 add_path() 的语法自撰写帖子以来已更改。我在旧问题中编辑了答案,但它不会立即显示,因为我还没有编辑批准权限。

如果更换

G.add_path([0,2,5])
G.add_path([1,4,3,0])
G.add_path([2,5])

nx.add_path(G,[0,5])
nx.add_path(G,[1,0])
nx.add_path(G,[2,5])

那么我相信它应该会成功运行。


编辑:为了回应下面的评论,这里是一个考虑到形状和大小的工作代码示例。它在风格上不是特别干净或一致,但它结合了 previous SO question 中的方法和提问者的数据生成方案。

关键部分从使用nx.draw()改为使用nx.draw_networkx_nodes()nx.draw_networkx_edges()nx.draw_networkx_labels()单独绘制图形的所有部分。请参阅 networkx drawing docs 了解完整详情。此更改允许使用不同的 nx.draw_networkx_nodes() 调用绘制具有不同形状的每组节点。

我做了一些相当不雅的事情来调整情节,包括调整plt.xlimplt.ylimk的间距参数(nx.layout.spring_layout())。

下面的代码给出了如下图:

network_viz_w_shapes_sizes

class Vert:
  
    # default constructor
    def __init__(self,name,size,edges):
        self.name = name
        self.size = size
        self.edges = edges


import networkx as nx
import matplotlib.pyplot as plt

nodes = []
nodes.append(Vert('A',1,['B','C']))
nodes.append(Vert('B',['D']))
nodes.append(Vert('C',['D']))
nodes.append(Vert('D',7,[]))
nodes.append(Vert('Y',64,[]))

G = nx.DiGraph()

for v  in nodes:
    # Assign 'v' shape to even nodes and square shape to odd nodes.
    if ord(v.name) % 2 == 0:
        G.add_node(v.name,size=v.size,shape='v')
    else:
        G.add_node(v.name,shape='s')
    for e in v.edges:
        G.add_edge(v.name,e)

shapes = set((aShape[1]['shape'] for aShape in G.nodes(data = True)))
pos = nx.layout.spring_layout(G,k=2) #Make k larger to space out nodes more.

for shape in shapes:
    nodelist=[node[0] for node in filter(lambda x: x[1]['shape']==shape,G.nodes(data = True))]
    sizes = [100 * node[1]['size'] for node in filter(lambda x: x[1]['shape']==shape,G.nodes(data = True))]
    #...filter and draw the subset of nodes with the same symbol in the positions that are now known through the use of the layout.
    nx.draw_networkx_nodes(G,pos,node_shape=shape,nodelist=nodelist,node_size=sizes)

# Draw the edges between the nodes and label them
nx.draw_networkx_edges(G,pos)
nx.draw_networkx_labels(G,pos)

plt.xlim(-2,2) # Expand limits if large nodes spill over plot.
plt.ylim(-2,2) # Expand limits if large nodes spill over plot.

plt.show()