networkx 中的平方节点与 matplotlib

squared nodes in networkx with matplotlib

在开始之前,我要指出这个问题似乎与 重复,但这里的解决方案根本无法在 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()

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

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

如果你更换

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

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

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


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

关键部分是从使用 nx.draw() 更改为使用 nx.draw_networkx_nodes()nx.draw_networkx_edges()nx.draw_networkx_labels() 单独绘制图形的所有部分。有关详细信息,请参阅 networkx drawing docs。此更改允许使用不同的 nx.draw_networkx_nodes().

调用绘制具有不同形状的每组节点

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

下面的代码给出了以下情节:

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:
    # 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, size=v.size, 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()