r - 如何将 data.frame 转换为树状结构对象,例如树状图

标签 r dataframe dendrogram

我有一个 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

实际数据中有更多的行和列。我怎么能像这样创建树状图的嵌套树结构对象:
         |---Ab---Abb
     A---|
     |   |---Ac---Acc
   --|                 /--Bad 
     |   |---Ba-------|
     B---|             \--Bae
         |---Bb---Bdd

最佳答案

数据框到 Newick

我在计算系统发育学方面取得了博士学位,并且在我生成这个代码的过程中的某个地方,当我以这种非标准格式(在系统发育意义上)获得一些数据时,我使用了一两次。该脚本遍历数据框,就像它是一棵树......并沿途将内容粘贴到 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=""))
    }

主要功能 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));"
    

    现在您可以将它读入类 phylo 的对象中。与 read.tree()从猿
        library(ape)
        mytree <- read.tree(text=myNewick)
        plot(mytree)
    

    如果要将内部节点标签添加到 Newick 字符串,可以使用以下命令:
        myNewick <- df2newick(df, TRUE)
        #[1] "((Abb,Acc)A,((Bad,Bae)Ba,Bdd)B);"
    

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

    数据帧格式的附加说明:

    正如您所观察到的 df2newick 函数忽略了一个 child 的内部模式(无论如何最好与大多数系统发育方法一起使用......只与我有关)。 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'))
    

    与您的非常相似……但是“内部单一子节点”只是与它们的子节点同名,但是您也有此节点的不同内部名称,并且这些名称会被忽略……可能不相关,但您可以只需忽略递归函数的一部分,如下所示:
        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) }
        }
    

    你会得到这样的东西:
        [1] "(((Abb)Ab,(Acc)Ac)A,((Bad,Bae)Ba,(Bdd)Bd)B);"
    

    这对我来说真的很奇怪,但我添加它以防万一,因为它现在确实包含来自原始数据帧的所有信息。

    关于r - 如何将 data.frame 转换为树状结构对象,例如树状图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15343338/

    相关文章:

    r - 将矩阵与 qq 图配对

    r - 从 R 列中的字符串创建 txt 文件

    python - Pandas :对同一列中的情侣进行分组

    r - 如何交叉粘贴两个向量的所有组合(每个向量)?

    基于R中的第二个变量删除具有非唯一值的行?

    python - Pandas 遍历指定行号的行

    python - 如何将 pandas DataFrame 的第一列作为一个系列?

    matplotlib - 如何根据定义的组为树状图的标签着色? (在Python中)

    python - 将 igraph 转换为 networkx 以进行聚类

    r - 抑制树状图中的叶标签