树表示法 (skbio.tree
)¶
这个模块提供了处理树的功能,包括系统进化树和层次结构。提供了构建树、以多种方式遍历、比较、获取子树等功能。此模块支持具有多个源的树和具有单个子代的节点。
Classes¶
|
树中节点的表示 |
系统发育重建¶
|
应用邻域连接进行系统发育重建。 |
工具函数¶
|
从根目录树的列表中确定一致树 |
例外情况¶
一般树错误 |
|
缺少预期长度 |
|
具有相同名称的重复节点 |
|
应为节点 |
|
缺少父类 |
示例
>>> from skbio import TreeNode
>>> from io import StringIO
可以从Newick字符串构造新树。Newick是一种常用格式,用于表示文件中的树对象。Newick是Joseph Felsenstein小组(定义 here ),并基于用括号表示嵌套。例如,下面的字符串描述了一个具有一个内部节点的3分类树:
((A, B)C, D)root;
其中A、B和D是树的顶端,C是覆盖提示A和B的内部节点。
现在我们来构造一个简单的ASCII表示:
>>> tree = TreeNode.read(StringIO("((A, B)C, D)root;"))
>>> print(tree.is_root()) # is this the root of the tree?
True
>>> print(tree.is_tip()) # is this node a tip?
False
>>> print(tree.ascii_art())
/-A
/C-------|
-root----| \-B
|
\-D
遍历树有几种常见的方法,根据您的使用情况,有些方法比其他方法更合适。维基百科在树上有一个写得很好的页面 traversal methods ,并将深入到我们将要讨论的深度。我们在这里只讨论两种常用的遍历,preorder和posterorder,但是我们将展示另外两种常见的helper遍历方法的示例,以收集提示或内部节点。
我们将要介绍的第一个遍历是一个预序遍历,在这个遍历中,从根到tips进行求值,首先查看最左边的子对象。例如:
>>> for node in tree.preorder():
... print(node.name)
root
C
A
B
D
下一个方法是postorder traveral,它将在返回树之前首先计算左子树提示:
>>> for node in tree.postorder():
... print(node.name)
A
B
C
D
root
TreeNode 还提供了两个helper方法,用于仅迭代提示或仅迭代内部节点。
>>> for node in tree.tips():
... print("Node name: %s, Is a tip: %s" % (node.name, node.is_tip()))
Node name: A, Is a tip: True
Node name: B, Is a tip: True
Node name: D, Is a tip: True
>>> for node in tree.non_tips():
... print("Node name: %s, Is a tip: %s" % (node.name, node.is_tip()))
Node name: C, Is a tip: False
注意,默认情况下, non_tips 将忽略 self (这是本例中的根)。你可以通过 include_self 旗到 non_tips 如果你想包括 self .
这个 TreeNode 提供了几种比较树的方法。首先,让我们创建两个相似的树并使用 compare_subsets . 此距离是两棵树中存在的共有分支的分数,其中距离0表示这些树包含相同的分支,距离1表示树不共享任何公共分支:
>>> tree1 = TreeNode.read(StringIO("((A, B)C, (D, E)F, (G, H)I)root;"))
>>> tree2 = TreeNode.read(StringIO("((G, H)C, (D, E)F, (B, A)I)root;"))
>>> tree3 = TreeNode.read(StringIO("((D, B)C, (A, E)F, (G, H)I)root;"))
>>> print(tree1.compare_subsets(tree1)) # identity case
0.0
>>> print(tree1.compare_subsets(tree2)) # same tree but different clade order
0.0
>>> print(tree1.compare_subsets(tree3)) # only 1 of 3 common subsets
0.6666666666666667
在计算树之间的距离时,我们还可以考虑树枝的长度。首先,我们将构造两个具有所描述的分支长度的新树,注意Newick字符串中的差异:
>>> tree1 = \
... TreeNode.read(StringIO("((A:0.1, B:0.2)C:0.3, D:0.4, E:0.5)root;"))
>>> tree2 = \
... TreeNode.read(StringIO("((A:0.4, B:0.8)C:0.3, D:0.1, E:0.5)root;"))
在这两个树中,我们添加了从节点到其父节点的长度描述,例如:
>>> for node in tree1.postorder():
... print(node.name, node.length)
A 0.1
B 0.2
C 0.3
D 0.4
E 0.5
root None
现在让我们比较两棵树,使用两棵树的尖端之间成对计算的距离。默认情况下,计算的距离是树之间所有成对的叶尖到叶尖距离的相关性:
>>> print(tree1.compare_tip_distances(tree1)) # identity case
0.0
>>> print(tree1.compare_tip_distances(tree2))
0.120492524415