Networkx:如何指定多个根以一次绘制多棵树?
Networkx: how to specify multiple roots for plotting multiple trees at once?
在 networkx 中有一个使用径向布局绘制树的函数(graphviz 的 "twopi"):
import pydot
from networkx.drawing.nx_pydot import graphviz_layout
pos = graphviz_layout(G, prog='twopi', root=root, args='')
可以使用参数 root
指定根节点(它作为 args += f" -Groot={root}"
添加到 args 中)。
但是当图由多个断开连接的组件组成时,如何指定多个根? IE。一片树林。
我在没有提供 root 参数的情况下得到了以下图:
正如你在视觉上看到的,虽然它为 10 棵树正确选择了真正的根节点,但对于 12 棵树,它选择了真正根节点的 child 作为中心(因此一些分支相对于其他分支看起来比实际更浅)。
如何手动指定多棵树的根?
我认为没有办法在使用 graphviz 的 twopi 布局的单个图形中执行此操作。 Twopi should 通常在设置每个子图的根节点方面做得很好,因为在 docs it will randomly pick one of the nodes that are furthest from a leaf node as root, so in the case of having a single root node, this should lead to the expected topological arrangement. Though if that is not the case, and you want to set manually the roots for each subgraph, the way I'd approach this is by iterating over the graphs connected component subgraphs, and plotting each component into an separate axis in a subplot graph, creating a custom graphviz_layout
中提到了每个子图。
以下是使用以下示例图完成此操作的方法:
from matplotlib import pyplot as plt
import pygraphviz
from networkx.drawing.nx_agraph import graphviz_layout
result_set = {('plant','tree'), ('tree','oak'), ('flower', 'rose'), ('flower','daisy'), ('plant','flower'), ('tree','pine'), ('plant','roots'), ('animal','fish'),('animal','bird'), ('bird','robin'), ('bird','falcon'), ('animal', 'homo'),('homo','homo-sapiens'), ('animal','reptile'), ('reptile','snake'),('fungi','mushroom'), ('fungi','mold'), ('fungi','toadstool'),('reptile','crocodile'), ('mushroom','Portabello'), ('mushroom','Shiitake'),('pine','roig'),('pine','pinyer'), ('tree','eucaliptus'),('rose','Floribunda'),('rose','grandiflora')}
G=nx.from_edgelist(result_set, create_using=nx.DiGraph)
为了迭代现有的子图,我们必须创建当前图的副本作为无向图(如果它还没有的话),并使用 nx.connected_component_subgraphs
:[=21 创建子图列表=]
UG = G.to_undirected()
subgraphs = list(nx.connected_component_subgraphs(UG))
假设我们知道我们希望不同组件的根节点是节点 'plant'
、'animal'
和 'mushroom'
,我们现在可以创建一组子图,并遍历各个轴,以及子图对象和根列表(确保它们的顺序相同),为每个设置相应根节点的子图创建一个新布局:
n_cols = 2
roots = ['plant','animal','mushroom']
fig, axes = plt.subplots(nrows=int(np.ceil(len(subgraphs)/n_cols)),
ncols=n_cols,
figsize=(15,10))
plt.box(False)
for subgraph, root, ax in zip(subgraphs, roots, axes.flatten()):
pos = graphviz_layout(G, prog='twopi', args=f"-Groot={root}")
nx.draw(subgraph, pos=pos, with_labels=True,
node_color='lightblue', node_size=500, ax=ax)
在 networkx 中有一个使用径向布局绘制树的函数(graphviz 的 "twopi"):
import pydot
from networkx.drawing.nx_pydot import graphviz_layout
pos = graphviz_layout(G, prog='twopi', root=root, args='')
可以使用参数 root
指定根节点(它作为 args += f" -Groot={root}"
添加到 args 中)。
但是当图由多个断开连接的组件组成时,如何指定多个根? IE。一片树林。
我在没有提供 root 参数的情况下得到了以下图:
正如你在视觉上看到的,虽然它为 10 棵树正确选择了真正的根节点,但对于 12 棵树,它选择了真正根节点的 child 作为中心(因此一些分支相对于其他分支看起来比实际更浅)。
如何手动指定多棵树的根?
我认为没有办法在使用 graphviz 的 twopi 布局的单个图形中执行此操作。 Twopi should 通常在设置每个子图的根节点方面做得很好,因为在 docs it will randomly pick one of the nodes that are furthest from a leaf node as root, so in the case of having a single root node, this should lead to the expected topological arrangement. Though if that is not the case, and you want to set manually the roots for each subgraph, the way I'd approach this is by iterating over the graphs connected component subgraphs, and plotting each component into an separate axis in a subplot graph, creating a custom graphviz_layout
中提到了每个子图。
以下是使用以下示例图完成此操作的方法:
from matplotlib import pyplot as plt
import pygraphviz
from networkx.drawing.nx_agraph import graphviz_layout
result_set = {('plant','tree'), ('tree','oak'), ('flower', 'rose'), ('flower','daisy'), ('plant','flower'), ('tree','pine'), ('plant','roots'), ('animal','fish'),('animal','bird'), ('bird','robin'), ('bird','falcon'), ('animal', 'homo'),('homo','homo-sapiens'), ('animal','reptile'), ('reptile','snake'),('fungi','mushroom'), ('fungi','mold'), ('fungi','toadstool'),('reptile','crocodile'), ('mushroom','Portabello'), ('mushroom','Shiitake'),('pine','roig'),('pine','pinyer'), ('tree','eucaliptus'),('rose','Floribunda'),('rose','grandiflora')}
G=nx.from_edgelist(result_set, create_using=nx.DiGraph)
为了迭代现有的子图,我们必须创建当前图的副本作为无向图(如果它还没有的话),并使用 nx.connected_component_subgraphs
:[=21 创建子图列表=]
UG = G.to_undirected()
subgraphs = list(nx.connected_component_subgraphs(UG))
假设我们知道我们希望不同组件的根节点是节点 'plant'
、'animal'
和 'mushroom'
,我们现在可以创建一组子图,并遍历各个轴,以及子图对象和根列表(确保它们的顺序相同),为每个设置相应根节点的子图创建一个新布局:
n_cols = 2
roots = ['plant','animal','mushroom']
fig, axes = plt.subplots(nrows=int(np.ceil(len(subgraphs)/n_cols)),
ncols=n_cols,
figsize=(15,10))
plt.box(False)
for subgraph, root, ax in zip(subgraphs, roots, axes.flatten()):
pos = graphviz_layout(G, prog='twopi', args=f"-Groot={root}")
nx.draw(subgraph, pos=pos, with_labels=True,
node_color='lightblue', node_size=500, ax=ax)