树表示法 (skbio.tree

这个模块提供了处理树的功能,包括系统进化树和层次结构。提供了构建树、以多种方式遍历、比较、获取子树等功能。此模块支持具有多个源的树和具有单个子代的节点。

Classes

TreeNode \ [name, length, support, parent, ...] )

树中节点的表示

系统发育重建

nj \(马克)[, disallow_negative_branch_length, ...] )

应用邻域连接进行系统发育重建。

工具函数

majority_rule \(树木[, weights, cutoff, ...] )

从根目录树的列表中确定一致树

例外情况

TreeError 

一般树错误

NoLengthError 

缺少预期长度

DuplicateNodeError 

具有相同名称的重复节点

MissingNodeError 

应为节点

NoParentError 

缺少父类

实际案例

>>> 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