python - Networkx:如何为一次绘制多棵树指定多个根?
问题描述
在 networkx 中有一个使用径向布局(graphviz 的“twopi”)绘制树的功能:
import pydot
from networkx.drawing.nx_pydot import graphviz_layout
pos = graphviz_layout(G, prog='twopi', root=root, args='')
可以使用参数指定根节点root
(在后台添加到 args 作为args += f" -Groot={root}"
)。
但是,当图形包含多个断开连接的组件时,如何指定多个根呢?即树木的森林。
我在不提供 root 参数的情况下得到以下图:
正如您在视觉上看到的那样,虽然它为 10 棵树正确选择了真正的根节点,但对于 12 棵树,它选择了真正根节点的一个子节点作为中心(因此,相对于其他分支)。
如何手动指定多棵树的根?
解决方案
我认为没有办法在带有graphviz的twopi布局的单个图中做到这一点。Twopi 通常应该在设置每个子图的根节点方面做得很好,因为如文档中所述,它会随机选择离叶节点最远的节点之一作为根,所以在有单个根的情况下节点,这应该导致预期的拓扑排列。虽然如果不是这种情况,并且您想手动设置每个子图的根,但我解决此问题的方法是迭代连接的组件子图,并将每个组件绘制到子图中的单独轴中,为每个人创建一个自定义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
:
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)
推荐阅读
- powerbi - Power bi 网关仅适用于一个来源
- c# - 如何在 _layout 中设置 cookie
- python - 我可以在 Python 的正则表达式中使用变量而不是常量吗
- mysql - 该字符串包含由连字符('-')分隔的多个子字符串。如何比较子字符串并删除重复的子字符串?
- maven - 如何关闭 intelij idea maven run debug console 的右侧分成两部分?
- ios - 基于用户在 ToDo DatePicker (Swift & SwiftUI) 中设置的日期时间的 iOS 本地通知
- google-cloud-firestore - 无法从 firestore 创建名为“timestamp”的字段的架构列
- javascript - 在 Quasar (vue) 中使用解析从数据中获取数据 - 返回未定义
- javascript - 远程通知不会触发notificationclick
- docker - 如何在来宾操作系统和 Docker 容器之间绑定目录?