Python 使用带有 0 和 1 的数据框制作 newick 格式

Python make newick format using dataframe with 0s and 1s

我有一个这样的数据框

      a b c d e f g h i j k l m
mut1  0 0 0 0 0 1 1 1 1 1 1 1 1 
mut2  0 0 0 0 0 1 1 1 1 1 0 0 0 
mut3  0 0 0 0 0 1 1 0 0 0 0 0 0 
mut4  0 0 0 0 0 1 0 0 0 0 0 0 0 
mut5  0 0 0 0 0 0 0 1 1 0 0 0 0 
mut6  0 0 0 0 0 0 0 1 0 0 0 0 0 
mut7  0 0 0 0 0 0 0 0 0 1 0 0 0 
mut8  0 0 0 0 0 0 0 0 0 0 1 1 1 
mut9  0 0 0 0 0 0 0 0 0 0 1 1 0 
mut10 0 0 0 0 0 0 0 0 0 0 0 0 1 
mut11 1 1 1 1 1 0 0 0 0 0 0 0 0 
mut12 1 1 1 0 0 0 0 0 0 0 0 0 0 
mut13 1 1 0 0 0 0 0 0 0 0 0 0 0 
mut14 1 0 0 0 0 0 0 0 0 0 0 0 0 
mut15 0 0 0 1 0 0 0 0 0 0 0 0 0 
mut16 0 0 0 0 1 0 0 0 0 0 0 0 0 

和原始对应的字符串

(a:0,b:0,c:0,d:0,e:0,f:0,g:0,h:0,i:0,j:0,k:0, l:0,m:0):0

我想的算法是这样的

在mut1行,我们可以看到f,g,h,i,j,k,l,m具有相同的特征。 所以字符串可以修改成

(a:0,b:0,c:0,d:0,e:0,(f:0,g:0,h:0,i:0,j:0,k:0 ,l:0,m:0):0):0

在mut2行,我们可以看到f,g,h,i,j具有相同的特征。 所以字符串可以修改成

(a:0,b:0,c:0,d:0,e:0,((f:0,g:0,h:0,i:0,j:0):0 ,k:0,l:0,m:0):0):0

直到mut10,它继续对f,g,h,i,j,k,l,m中的样本进行聚类。

输出将是

(a:0,b:0,c:0,d:0,e:0,(((f:0,g:0):0,(h:0,i:0): 0,j:0):0,((k:0,l:0):0,m:0):0):0):0

(有一个“1”的行,跳过该过程)

从 mut10 开始,它开始聚类样本 a、b、c、d、e

同样,最终输出将是

(((a:0,b:0):0,c:0):0,d:0,e:0,(((f:0,g:0):0,(h :0,i:0):0,j:0):0,((k:0,l:0):0,m:0):0):0):0

所以算法是

  1. 将具有相同特征的样本聚类。
  2. 聚类后,在右括号后添加“:0”。

对这个过程有什么建议吗?

*p.s。我上传了类似的问题 Creating a newick format from dataframe with 0 and 1 但是这个更详细。

您的问题在 Python 中寻求解决方案,我对此并不熟悉。希望 R 中的以下过程也会有所帮助。

你的问题描述的是树的矩阵表示。可以使用 phangorn 包使用最大简约法从矩阵中检索出这样的树。要在 R 中操作树,newick 格式很有用。 Newick 与您问题中的树表示不同,它以分号结尾。

首先,准备一棵phylo格式的起始树。

library(phangorn)
tree0 <- read.tree(text = "(a,b,c,d,e,f,g,h,i,j,k,l,m);")

其次,将您的 data.frame 转换为 phyDat 对象,其中行代表样本和列特征。 phyDat 对象还需要数据中存在的级别,在本例中为 0 和 1。结合起始树和数据,我们计算出最大简约树。

dat0 = read.table(text = "      a b c d e f g h i j k l m
    mut1  0 0 0 0 0 1 1 1 1 1 1 1 1 
    mut2  0 0 0 0 0 1 1 1 1 1 0 0 0 
    mut3  0 0 0 0 0 1 1 0 0 0 0 0 0 
    mut4  0 0 0 0 0 1 0 0 0 0 0 0 0 
    mut5  0 0 0 0 0 0 0 1 1 0 0 0 0 
    mut6  0 0 0 0 0 0 0 1 0 0 0 0 0 
    mut7  0 0 0 0 0 0 0 0 0 1 0 0 0 
    mut8  0 0 0 0 0 0 0 0 0 0 1 1 1 
    mut9  0 0 0 0 0 0 0 0 0 0 1 1 0 
    mut10 0 0 0 0 0 0 0 0 0 0 0 0 1 
    mut11 1 1 1 1 1 0 0 0 0 0 0 0 0 
    mut12 1 1 1 0 0 0 0 0 0 0 0 0 0 
    mut13 1 1 0 0 0 0 0 0 0 0 0 0 0 
    mut14 1 0 0 0 0 0 0 0 0 0 0 0 0 
    mut15 0 0 0 1 0 0 0 0 0 0 0 0 0 
    mut16 0 0 0 0 1 0 0 0 0 0 0 0 0")

dat1 <- phyDat(data = t(dat0), 
    type = "USER",
    levels = c(0, 1))

tree1 <- optim.parsimony(tree = tree0, data = dat1)
plot(tree1)

树现在包含一个没有分支长度的分支图。 Class phylo 实际上是一个列表,因此零分支长度可以作为额外元素添加。

tree2 <- tree1
tree2$edge.length <- rep(0, nrow(tree2$edge))

最后,我们将树写成newick格式的字符向量,去掉末尾的分号,符合要求

tree3 <- write.tree(tree2)
tree3 <- sub(";", "", tree3)
tree3
# [1] "((e:0,d:0):0,(c:0,(b:0,a:0):0):0,((m:0,(l:0,k:0):0):0,((i:0,h:0):0,j:0,(g:0,f:0):0):0):0)"