绘制带有节点标签的networkx图,默认为节点名称

时间:2015-02-16 00:59:08

标签: networkx

NetworkX很强大,但我试图绘制一个默认显示节点标签的图表,我很惊讶这个看似简单的任务对于Networkx的新手来说是多么乏味。有一个示例显示如何向图中添加标签。

https://networkx.github.io/documentation/latest/examples/drawing/labels_and_colors.html

这个例子的问题是,当我想要做的只是在绘制图形时显示与节点名称相同的标签时,它使用了太多的步骤和方法。

# Add nodes and edges
G.add_node("Node1")
G.add_node("Node2")
G.add_edge("Node1", "Node2")
nx.draw(G)    # Doesn't draw labels. How to make it show labels Node1, Node2 along?

有没有办法让nx.draw(G)在图表中内联显示默认标签(本例中为Node1,Node2)?

2 个答案:

答案 0 :(得分:60)

tl / dr:只需将with_labels=True添加到nx.draw来电。

你看到的page有点复杂,因为它如何设置许多不同的东西作为标签,如何给不同的节点提供不同的颜色,以及如何提供仔细控制节点位置。

您似乎只希望每个节点都使用自己的名称,并且您对默认颜色和默认位置感到满意。所以

import networkx as nx
import pylab as plt

G=nx.Graph()
# Add nodes and edges
G.add_edge("Node1", "Node2")
nx.draw(G, with_labels = True)
plt.savefig('labels.png')

enter image description here

如果你想做某事以使节点标签不同,你可以发送一个dict作为参数。例如,

labeldict = {}
labeldict["Node1"] = "shopkeeper"
labeldict["Node2"] = "angry man with parrot"

nx.draw(G,labels=labeldict, with_labels = True)

enter image description here

答案 1 :(得分:-1)

我觉得更好的答案是不要用networkx来画。他们明确警告你图可视化很难,networkx 主要用于图分析(来自 https://networkx.org/documentation/stable/reference/drawing.html#module-networkx.drawing.layout):

<块引用>

绘图 NetworkX 提供可视化图形的基本功能,但其主要目标是启用图形分析而不是执行图形可视化。将来,图形可视化功能可能会从 NetworkX 中删除或仅作为附加包提供。

<块引用>

正确的图形可视化很难,我们强烈建议人们使用专用于该任务的工具来可视化他们的图形。 Cytoscape、Gephi、Graphviz 和用于 LaTeX 排版的 PGF/TikZ 是专用且功能齐全的图形可视化工具的显着示例。要使用这些工具和其他此类工具,您应该将 NetworkX 图形导出为这些工具可以读取的格式。例如,Cytoscape 可以读取 GraphML 格式,因此 networkx.write_graphml(G, path) 可能是一个合适的选择。

因此,我的建议是将图形转换为具有用于图形可视化的专用软件的某种格式,然后进行绘制(例如 pydot、pygraphviz、graphviz 等)。我怀疑 pydot 和 pygraphviz 出于某种原因是最好的,因为 networkx 只支持这两个。从 pygraphviz 中的文档看来,它有一个类似的 api,因此如果您已经想使用 networkx (https://pygraphviz.github.io/documentation/stable/tutorial.html),它可能是最容易使用的:

<块引用>

API 与 NetworkX 的 API 非常相似。 https://networkx.org/documentation/latest/tutorial.html 中的大部分 NetworkX 教程都适用于 PyGraphviz。请参阅 http://pygraphviz.github.io/documentation/latest/reference/api_notes.html 了解主要差异。

此外,到目前为止,pydot 还没有真正的文档(这让我很困扰。如果是它在我的浏览器上看起来不好看,或者它让我觉得该项目没有被它的开发人员认真对待,我想知道即使 pydot 15k 与 pygraphviz 4k 的用户群更高,idk 也感觉不对劲)参考:https://github.com/pydot/pydot/pull/241

此外,pygraphviz 似乎比常规的 graphviz ref 具有更精细的控制:Graphviz vs PyGraphViz。此外,我不知道如何将 networkx 直接转换为 graphviz obj(因为 graphviz 拥有最好的文档和最高的用户群~19k,所以我确实更喜欢那个),因此出于这些原因,我将使用 pygraphviz。 Pygravix 也有文档,虽然很小,但让我很高兴(虽然不如 graphviz 但知道如何从 networkx 制作 graphviz 图)。做出这些决定很难,但我不能永远坚持下去,这似乎已经足够了。此外,networkx 也很好,因为我也可以将 dgl 图转换为 networkx(并且重新标记很简单)。

考虑到这些原因,让我为您提供我编写的示例代码,该代码使用 pygraphviz 执行您想要的操作(但如果您知道如何使用 pydot,则可以使用 pydot 来完成,使用 networkx 转换为 pydot obj 是微不足道的,请参阅我之前的链接):

# https://stackoverflow.com/questions/28533111/plotting-networkx-graph-with-node-labels-defaulting-to-node-name

import dgl
import numpy as np
import torch

import networkx as nx

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

from pathlib import Path

g = dgl.graph(([0, 0, 0, 0, 0], [1, 2, 3, 4, 5]), num_nodes=6)
print(f'{g=}')
print(f'{g.edges()=}')

# Since the actual graph is undirected, we convert it for visualization purpose.
g = g.to_networkx().to_undirected()
print(f'{g=}')

# relabel
int2label = {0: "app", 1: "cons", 2: "with", 3: "app3", 4: "app4", 5: "app5"}
g = nx.relabel_nodes(g, int2label)

# https://networkx.org/documentation/stable/reference/drawing.html#module-networkx.drawing.layout
g = nx.nx_agraph.to_agraph(g)
print(f'{g=}')
print(f'{g.string()=}')

# draw
g.layout()
g.draw("file.png")

# https://stackoverflow.com/questions/20597088/display-a-png-image-from-python-on-mint-15-linux
img = mpimg.imread('file.png')
plt.imshow(img)
plt.show()

# remove file https://stackoverflow.com/questions/6996603/how-to-delete-a-file-or-folder
Path('./file.png').expanduser().unlink()
# import os
# os.remove('./file.png')

输出:

g=Graph(num_nodes=6, num_edges=5,
      ndata_schemes={}
      edata_schemes={})
g.edges()=(tensor([0, 0, 0, 0, 0]), tensor([1, 2, 3, 4, 5]))
g=<networkx.classes.multigraph.MultiGraph object at 0x7f8443e94250>
g=<AGraph <Swig Object of type 'Agraph_t *' at 0x7f846117a930>>
g.string()='graph "" {\n\tapp -- cons [key=0,\n\tid=0];\napp -- with [key=0,\nid=1];\napp -- app3 [key=0,\nid=2];\napp -- app4 [key=0,\nid=3];\napp -- app5 [key=0,\nid=4];\n}\n'

虽然我想留下这个关于 pydot 可视化的链接,因为它在一般情况下似乎非常有用:Display graph without saving using pydot 并且可能会在其他人需要时为他们提供 pydot 答案。不过,我希望看到支持 pydot 的论据。


Edit1:如果您想按属性而不是按标签进行绘图,请参阅此答案:NetworkX node attribute drawing 请注意,按照我建议的方式重新标记并不总是具有预期的语义(例如,它可能会连接两个不是打算加入)。


Edit2:如果您想在不意外发生自循环的情况下绘制属性,请参阅此答案:Draw more information on graph\nodes using PyGraphviz

相关问题