我想用networkx绘制一个简单的图表。每个节点中都有两个带有Python和编程标签的节点。代码和图形如下:
import networkx as nx
G = nx.DiGraph()
G.add_node(0)
G.add_node(1)
G.add_edge(0,1)
nx.draw_networkx(G,
pos = {0:(0, 0), 1: (1, 0)},
node_size = [1000, 2000],
node_color = ["red","green"],
node_shape = "s",
)

我可以在两个节点中分别得到两个不同的颜色--红色和绿色,以及在每个节点中设置不同的标签。但是,我也想得到两个不同形状的节点。我希望有第一个节点,因为它是,第二节点的钻石形状,可以获得使用d在node_shape。我尝试以["s","d"]的形式传递列表,并在node_shape中以{0:"s", 1:"d"}的形式传递字典。
但是,两者都返回一个错误。我怎么能在这里得到不同形状的节点?是否可以使用其他库,如graphviz,如何使用?
在另一个步骤中,我希望将标签封装在节点中。因此,我将node_size设置为0,并使用bbox,如下所示。
nx.draw_networkx(G,
pos = {0:(0, 0), 1: (1, 0)},
node_size = 0,
arrows = True,
labels = {0:"Python",1:"Programming"},
bbox = dict(facecolor = "skyblue")
)

我可以将标签封装在bbox中,但是箭头并不隐藏,两个节点中bbox的外观颜色是相同的。在这种情况下,我怎样才能使面部颜色不同呢?解决这个问题的另一种方法是什么?
发布于 2022-04-21 21:12:59
我想出了一个用graphviz包来做这件事的方法。NetworkX包的限制是它不允许节点具有不同的形状,尽管大小或颜色可以以列表的形式不同设置。此外,如果使用边界框(bbox),则其属性在节点之间是一致的。
然而,graphviz在这种情况下提供了更多的灵活性。每个节点的形状、大小和颜色可以单独调整。我是这样做的:
import graphviz
G = graphviz.Digraph()
G.node("Python", style = 'filled', color = "red", shape = "box")
G.node("Programming", style = "filled", color = "green", shape = "ellipse")
G.edge("Python","Programming")
G.view()因此,我得到了如下情节:

还可以进一步定制图形,如节点位置、边缘颜色等。
发布于 2022-03-18 15:08:56
Networkx不支持一个函数调用中的多个节点形状,因为节点是使用matplotlib的scatter绘制的,后者不支持在同一个函数调用中绘制不同的标记。但是,您可以对nx.draw_networkx_nodes进行多次调用,每个调用都具有不同的节点和形状子集。
将标签封装在节点中是一项棘手的工作。文本框尺寸不能在matplotlib中预先计算,因为它支持多个呈现体。因此,您必须绘制一些虚拟文本对象,确定文本框的大小,然后向后返回到所需的大小。networkx中不包含这种功能。
如果您愿意使用其他库,那么大多数您想要的特性都可以很容易地在netgraph中实现,这是我编写和维护的一个库。支持在一个函数调用中绘制不同的节点形状。箭头应保持可见。更改节点标签背景色是相当容易的。
关于字体大小,在not中,如果没有显式设置节点标签的字体大小,它将计算出最大字体大小,以便所有文本框都适合对应的节点艺术家。正如您在下面的示例中所看到的,该计算存在一个小问题,因为当前的实现呈现一个圆形节点形状,因此第一个节点的文本框并不完全适合正方形节点。我将很快解决这个问题;同时,您必须使用更多的圆形节点形状,或者在一个单独的调用中调整字体大小,如下所示。

#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from netgraph import Graph # pip install netgraph
graph_data = nx.DiGraph([(0, 1)]) # edge lists or igraph Graph objects are also supported
g = Graph(graph_data,
node_layout = {0: (0, 0), 1: (1, 0)},
node_size = {0 : 10, 1 : 20},
node_color = {0 : "red", 1 : "green"},
node_labels = {0:"Python", 1:"Programming"},
node_label_fontdict = {'backgroundcolor' : 'lightgray'},
node_shape = {0 : "s", 1 : "d"},
arrows=True,
)
# Netgraph currently does not support multiple values for label backgroundcolors.
# However, all artists are exposed in simple to query dictionaries.
# As node label artists are matplotlib text objects,
# we can vary the node label background colors by using matplotlib.text.Text methods:
g.node_label_artists[0].set_backgroundcolor('salmon')
g.node_label_artists[1].set_backgroundcolor('lightgreen')
# Netgraph assumes circular node shapes when computing fontsizes.
# We hence have to manually adjust the node label fontsizes
# by the ratio of the diagonal to the width in a square.
for node, label in g.node_label_artists.items():
fontsize = label.get_fontsize()
label.set_fontsize(fontsize * 1./np.sqrt(2))
plt.show()发布于 2022-04-22 02:05:59
我正在测试Python库,它允许更直观、更友好地绘制图形。我考虑了标记节点的正确连接、不同类型的标签、可以用鼠标拖动的元素以及其他类型的交互。在大多数这些特性中,netgraph看起来很有前途,但不幸的是,它不支持矩形节点和边缘端位置的动态偏移,这对于能够以所需的方式显示有向边缘是必不可少的。事实上,节点和边是matplotlib路径对象,标签在netgraph中是matplotlib文本对象,这意味着矩形文本标签和文本包围的正确连接变得复杂,即使覆盖它的任何一个方法。
另一方面,如果使用networkx连接节点标签,则可以在matplotlib注释中解决这些问题。在本例中,只需要对节点进行注释的networkx.Graph和自定义艺术家:
import matplotlib.pyplot as plt
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([(0, 1)])
G.add_nodes_from([0, 1])
pos = {0:(0.1, 0.9), 1: (0.1, 0.1)}
fig, ax = plt.subplots()
annotations = {0: ax.annotate('Python', xy=pos[0], xycoords='data', size=20,
ha="center", va="center", bbox=dict(facecolor = "blue")),
1:ax.annotate('programming', xy=pos[1], xycoords='data',
ha="center", va="center", bbox=dict(facecolor = "red"))}
for A, B in G.edges:
ax.annotate("", xy=pos[B], xycoords='data', xytext=pos[A], textcoords='data',
arrowprops=dict(arrowstyle="->", color="0.5", # shrinkA=85, shrinkB=85,
patchA=annotations[A],
patchB=annotations[B],
connectionstyle='arc3'))
plt.axis('off')
plt.show()

另一种灵活性
此外,matplotlib还允许为节点标记提供更多别致的样式:
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnnotationBbox, TextArea, VPacker
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([(0,1), (1,2), (0, 2)])
G.add_nodes_from([0, 1, 2])
pos = {0:(0.1, 0.9), 1: (0.1, 0.1), 2: (0.9, 0.5)}
fig, ax = plt.subplots()
textobjs = [TextArea('IS', textprops=dict(color="blue", size=18, ha='left',va='baseline')),
TextArea('FUN!', textprops=dict(color="red", size=18, ha='left',va='baseline'))]
ybox = VPacker(children=textobjs, pad=0, sep=0)
anbox = AnnotationBbox(ybox, pos[2], frameon=True, box_alignment=(0,.5),
bboxprops=dict(facecolor='yellow', boxstyle='round'))
annotations = {0: ax.annotate('Python', xy=pos[0], xycoords='data',
ha="center", va="center", bbox=dict(facecolor = "blue")),
1:ax.annotate('programming', xy=pos[1], xycoords='data',
ha="center", va="center", bbox=dict(facecolor = "red")),
2:ax.add_artist(anbox)}
annotations[2].draggable()
for A, B in G.edges:
ax.annotate("", xy=pos[B], xycoords='data', xytext=pos[A], textcoords='data',
arrowprops=dict(arrowstyle="->", color="0.5", # shrinkA=85, shrinkB=85,
patchA=annotations[A],
patchB=annotations[B],
connectionstyle='arc3'))
plt.axis('off')
plt.show()

https://stackoverflow.com/questions/71520067
复制相似问题