【问题标题】:Extract labels membership / classification from a cut dendrogram in R (i.e.: a cutree function for dendrogram)从 R 中的切割树状图中提取标签成员资格/分类(即:树状图的 cutree 函数)
【发布时间】:2014-10-16 15:06:55
【问题描述】:

我正在尝试从 R 中的树状图中提取一个分类,我在某个高度有 cut。在hclustobject 上使用cutree 很容易做到这一点,但我不知道如何在dendrogram 对象上做到这一点。

此外,我不能只使用原始 hclust 中的集群,因为(令人沮丧)cutree 中的类编号与 cut 中的类编号不同。

hc <- hclust(dist(USArrests), "ave")

classification<-cutree(hc,h=70)

dend1 <- as.dendrogram(hc)
dend2 <- cut(dend1, h = 70)


str(dend2$lower[[1]]) #group 1 here is not the same as
classification[classification==1] #group 1 here

有没有办法让分类相互映射,或者从dendrogram对象中提取较低的分支成员资格(也许巧妙地使用dendrapply?)格式更像@ 987654330@给?

【问题讨论】:

    标签: r classification cluster-analysis dendrogram dendextend


    【解决方案1】:

    我最终使用dendrapply 创建了一个函数来执行此操作。它并不优雅,但它确实有效

    classify <- function(dendrogram,height){
    
    #mini-function to use with dendrapply to return tip labels
     members <- function(n) {
        labels<-c()
        if (is.leaf(n)) {
            a <- attributes(n)
            labels<-c(labels,a$label)
        }
        labels
     }
    
     dend2 <- cut(dendrogram,height) #the cut dendrogram object
     branchesvector<-c()
     membersvector<-c()
    
     for(i in 1:length(dend2$lower)){                             #for each lower tree resulting from the cut
      memlist <- unlist(dendrapply(dend2$lower[[i]],members))     #get the tip lables
      branchesvector <- c(branchesvector,rep(i,length(memlist)))  #add the lower tree identifier to a vector
      membersvector <- c(membersvector,memlist)                   #add the tip labels to a vector
     }
    out<-as.integer(branchesvector)                               #make the output a list of named integers, to match cut() output
    names(out)<-membersvector
    out
    }
    

    使用该函数可以清楚地看出问题是cut按字母顺序分配类别名称,而cutree从左到右分配分支名称。

    hc <- hclust(dist(USArrests), "ave")
    dend1 <- as.dendrogram(hc)
    
    classify(dend1,70) #Florida 1, North Carolina 1, etc.
    cutree(hc,h=70)    #Alabama 1, Arizona 1, Arkansas 1, etc.
    

    【讨论】:

      【解决方案2】:

      我建议您使用 dendextend 包中的 cutree 函数。它包括一个树状图方法(即:dendextend:::cutree.dendrogram)。

      您可以通过its introductory vignette了解更多关于该软件包的信息。

      我应该补充一点,虽然您的功能 (classify) 很好,但使用 dendextend 中的cutree 有几个优势:

      1. 它还允许您使用特定的k(簇数),而不仅仅是h(特定的高度)。

      2. 这与您在 hclust 上从 cutree 获得的结果一致(classify 不会)。

      3. 通常会更快。

      以下是使用代码的示例:

      # Toy data:
      hc <- hclust(dist(USArrests), "ave")
      dend1 <- as.dendrogram(hc)
      
      # Get the package:
      install.packages("dendextend")
      library(dendextend)
      
      # Get the package:
      cutree(dend1,h=70) # it now works on a dendrogram
      # It is like using:
      dendextend:::cutree.dendrogram(dend1,h=70)
      

      顺便说一句,在这个功能的基础上,dendextend允许用户做更多很酷的事情,比如基于切割树状图的颜色分支/标签:

      dend1 <- color_branches(dend1, k = 4)
      dend1 <- color_labels(dend1, k = 5)
      plot(dend1)
      

      最后,这里还有一些代码来展示我的其他观点:

      # This would also work with k:
      cutree(dend1,k=4)
      
      # and would give identical result as cutree on hclust:
      identical(cutree(hc,h=70)  , cutree(dend1,h=70)  )
         # TRUE
      
      # But this is not the case for classify:
      identical(classify(dend1,70)   , cutree(dend1,h=70)  )
         # FALSE
      
      
      install.packages("microbenchmark")
      require(microbenchmark)
      microbenchmark(classify = classify(dend1,70),
                     cutree = cutree(dend1,h=70)  )
      #    Unit: milliseconds
      #        expr      min       lq   median       uq       max neval
      #    classify  9.70135  9.94604 10.25400 10.87552  80.82032   100
      #      cutree 37.24264 37.97642 39.23095 43.21233 141.13880   100
      # 4 times faster for this tree (it will be more for larger trees)
      
      # Although (if to be exact about it) if I force cutree.dendrogram to not go through hclust (which can happen for "weird" trees), the speed will remain similar:
      microbenchmark(classify = classify(dend1,70),
                     cutree = cutree(dend1,h=70, try_cutree_hclust = FALSE)  )
      # Unit: milliseconds
      #        expr       min        lq    median       uq      max neval
      #    classify  9.683433  9.819776  9.972077 10.48497 29.73285   100
      #      cutree 10.275839 10.419181 10.540126 10.66863 16.54034   100
      

      如果您正在考虑改进此功能的方法,请在此处进行修补:

      https://github.com/talgalili/dendextend/blob/master/R/cutree.dendrogram.R

      我希望您或其他人会发现此答案对您有所帮助。

      【讨论】:

      • 非常感谢您的回答和开发这个精彩的软件包!
      • 感谢 Oreotrephes 的客气话。如果您遇到任何问题或您认为有帮助的新功能,请告诉我。最好的,塔尔
      • 有没有办法从color_branches(dend1, k = 4)提取小组作业?
      • 我有兴趣从 color_branches() 中提取小组作业
      【解决方案3】:

      制作树状图后,使用 cutree 方法,然后将其转换为数据框。以下代码使用库 dendextend 制作了一个漂亮的树状图:

      library(dendextend)
      
      # set the number of clusters
      clust_k <- 8
      
      # make the hierarchical clustering
      par(mar = c(2.5, 0.5, 1.0, 7))
      d <- dist(mat, method = "euclidean")
      hc <- hclust(d)
      dend <- d %>% hclust %>% as.dendrogram
      labels_cex(dend) <- .65
      dend %>% 
        color_branches(k=clust_k) %>%
        color_labels() %>%
        highlight_branches_lwd(3) %>% 
        plot(horiz=TRUE, main = "Branch (Distribution) Clusters by Heloc Attributes", axes = T)
      

      根据着色方案,看起来集群是在阈值 4 附近形成的。因此,要将分配放入数据帧,我们需要获取集群,然后 unlist() 它们。

      首先您需要自己获取集群,但是,它只是数字的单个向量,行名是实际的标签。

      # creates a single item vector of the clusters    
      myclusters <- cutree(dend, k=clust_k, h=4)
      
      # make the dataframe of two columns cluster number and label
      clusterDF <-  data.frame(Cluster = as.numeric(unlist(myclusters)),
                               Branch = names(myclusters))
      
      # sort by cluster ascending
      clusterDFSort <- clusterDF %>% arrange(Cluster)
      

      【讨论】:

        猜你喜欢
        • 2018-06-18
        • 1970-01-01
        • 2017-04-27
        • 1970-01-01
        • 2019-07-07
        • 1970-01-01
        • 2016-07-31
        • 2014-07-31
        • 1970-01-01
        相关资源
        最近更新 更多