我想知道如何从networkx
有向图中构建ete3.Tree
对象?我添加了每个child
的方式,我认为可以产生预期的结果,但我有麻烦。在
edges = [('lvl-1', 'lvl-2.1'), ('lvl-1', 'lvl-2.2'), ('lvl-2.1', 'lvl-3.1'), ('lvl-2.1', 2), ('lvl-2.2', 4), ('lvl-2.2', 6), ('lvl-3.1', 'lvl-4.1'), ('lvl-3.1', 5), ('lvl-4.1', 1), ('lvl-4.1', 3), ('input', 'lvl-1')]
graph = nx.OrderedDiGraph()
graph.add_edges_from(edges)
nx.draw(graph, pos=nx.nx_agraph.graphviz_layout(graph, prog="dot"), with_labels=True, node_size=1000, node_color="lightgray")
^{pr2}$
我也尝试了以下方法,但没有奏效:
tree = ete3.Tree()
for parent, child in graph.edges():
if parent not in tree:
tree.add_child(name=parent)
subtree = tree.search_nodes(name=parent)[0]
subtree.add_child(name=child)
print(tree)
# /-1
# /-|
# /-| \-3
# | |
# /-| \-5
# | |
# /-| \-2
# | |
# | | /-4
# --| \-|
# | \-6
# |
# \- /-lvl-1
子树和从networkX对象读取都是正常的,问题是您将所有子树直接添加到原始的
tree
实例中。在ete3中,Tree
类是in fact just a Node(包括指向其后代的指针,如果有的话),因此tree.add_child
直接向根节点添加新的子节点/子树。在您应该做的是iterate over the leaves of ete tree,找到
node.name == parent
的那个,并将所有子元素附加到它上。另外,您应该逐个附加它们,而不是预先生成子树。否则,您将获得具有单个父节点和单个子节点的附加内部节点。在编辑:
代码的第二个版本几乎是正确的,但是您没有考虑到如果根不是它们的实际父节点,则节点永远不会被附加到树(ieroot)。这可能就是为什么您将
lvl-1
作为一个单独的节点,而不是其他节点的父节点。另外,我不确定networkX图的遍历顺序,这可能很重要。更安全(如果更丑)的版本应该是这样的:可能有几个打字错误,而且绝对是超慢。从边缘计数到O(n**2)或更糟的东西,包括所有的迭代和列表删除。可能有一种方法可以将图从根遍历到叶,这不需要边列表的副本(只需一次迭代即可工作)。但它最终会产生一棵正确的树。在
相关问题 更多 >
编程相关推荐