如何将data.frame转换为树形结构对象,如树形图

RNA*_*RNA 15 r dendrogram dataframe

我有一个data.frame对象.举个简单的例子:

> data.frame(x=c('A','A','B','B','B'), y=c('Ab','Ac','Ba', 'Ba','Bd'), z=c('Abb','Acc','Bad', 'Bae','Bdd'))
  x  y   z
1 A Ab Abb
2 A Ac Acc
3 B Ba Bad
4 B Ba Bae
5 B Bd Bdd
Run Code Online (Sandbox Code Playgroud)

实际数据中有更多的行和列.我怎么能像这样创建树状图的嵌套树结构对象:

         |---Ab---Abb
     A---|
     |   |---Ac---Acc
   --|                 /--Bad 
     |   |---Ba-------|
     B---|             \--Bae
         |---Bb---Bdd
Run Code Online (Sandbox Code Playgroud)

Mar*_*jak 16

数据框架到纽尼克

我在计算系统发育学方面做了博士学位,并且在我制作这段代码的过程中,当我以这种非标准格式获得一些数据时(在系统发育意义上),我使用过一次或两次.该脚本遍历数据帧,就好像它是一棵树......并沿着路径粘贴到Newick字符串中,这是一种标准格式,然后可以在任何类型的树对象中进行转换.

我想这个脚本可以进行优化(我很少使用它,因此更多的工作会降低整体效率),但至少分享比让它收集硬盘上的灰尘更好.

    ## recursion function
    traverse <- function(a,i,innerl){
        if(i < (ncol(df))){
            alevelinner <- as.character(unique(df[which(as.character(df[,i])==a),i+1]))
            desc <- NULL
            if(length(alevelinner) == 1) (newickout <- traverse(alevelinner,i+1,innerl))
            else {
                for(b in alevelinner) desc <- c(desc,traverse(b,i+1,innerl))
                il <- NULL; if(innerl==TRUE) il <- a
                (newickout <- paste("(",paste(desc,collapse=","),")",il,sep=""))
            }
        }
        else { (newickout <- a) }
    }

    ## data.frame to newick function
    df2newick <- function(df, innerlabel=FALSE){
        alevel <- as.character(unique(df[,1]))
        newick <- NULL
        for(x in alevel) newick <- c(newick,traverse(x,1,innerlabel))
        (newick <- paste("(",paste(newick,collapse=","),");",sep=""))
    }
Run Code Online (Sandbox Code Playgroud)

main函数df2newick()有两个参数:

  • df 这是要转换的数据帧(类data.frame的对象)
  • innerlabel 告诉函数为内部节点写入标签(bulean)

要在您的示例中演示它:

    df <- data.frame(x=c('A','A','B','B','B'), y=c('Ab','Ac','Ba', 'Ba','Bd'), z=c('Abb','Acc','Bad', 'Bae','Bdd'))
    myNewick <- df2newick(df)
    #[1] "((Abb,Acc),((Bad,Bae),Bdd));"
Run Code Online (Sandbox Code Playgroud)

现在,你可以读入类的对象phyloread.tree()从猿

    library(ape)
    mytree <- read.tree(text=myNewick)
    plot(mytree)
Run Code Online (Sandbox Code Playgroud)

如果要将内部节点标签添加到Newick字符串,可以使用以下命令:

    myNewick <- df2newick(df, TRUE)
    #[1] "((Abb,Acc)A,((Bad,Bae)Ba,Bdd)B);"
Run Code Online (Sandbox Code Playgroud)

希望这是有用的(也许我的博士不是时间的完整;-)


您的数据框格式的附加说明:

正如你可以观察到df2newick函数忽略了一个孩子的内部模式(无论如何最好与大多数系统发育方法一起使用......只与我有关).df我最初获得并与此脚本一起使用的对象具有以下格式:

    df <- data.frame(x=c('A','A','B','B','B'), y=c('Abb','Acc','Ba', 'Ba','Bdd'), z=c('Abb','Acc','Bad', 'Bae','Bdd'))
Run Code Online (Sandbox Code Playgroud)

与你的非常相似......但是"内部儿童节点"与他们的孩子名称相同,但你们对这个节点也有不同的内部名称,名字被忽略......可能不相关但你可以只是忽略递归函数的一部分,如下所示:

    traverse <- function(a,i,innerl){
        if(i < (ncol(df))){
            alevelinner <- as.character(unique(df[which(as.character(df[,i])==a),i+1]))
            desc <- NULL
            ##if(length(alevelinner) == 1) (newickout <- traverse(alevelinner,i+1,innerl))
            ##else {
                for(b in alevelinner) desc <- c(desc,traverse(b,i+1,innerl))
                il <- NULL; if(innerl==TRUE) il <- a
                (newickout <- paste("(",paste(desc,collapse=","),")",il,sep=""))
            ##}
        }
        else { (newickout <- a) }
    }
Run Code Online (Sandbox Code Playgroud)

你会得到这样的东西:

    [1] "(((Abb)Ab,(Acc)Ac)A,((Bad,Bae)Ba,(Bdd)Bd)B);"
Run Code Online (Sandbox Code Playgroud)

这对我来说真的很奇怪,但我添加它只是为了以防万一,因为它真的包含了原始数据帧中的所有信息.