【问题标题】:How to color branches in R dendogram as a function of the classes in it?如何根据其中的类对 R 树状图中的分支进行着色?
【发布时间】:2018-01-07 23:49:50
【问题描述】:

我希望可视化聚类算法的效果(使用一定的距离度量)。我有样本及其相应的类。 为了形象化,我进行了聚类,并希望通过聚类中的项目为树状图的分​​支着色。颜色将是层次集群中大多数项对应的颜色(由数据\类给出)。

示例:如果我的聚类算法选择索引 1、21、24 作为某个集群(在某个级别),并且我有一个 csv 文件,其中包含对应于 1、2、1 的每一行中的类号。我希望这条边的颜色为 1。

示例代码:

require(cluster)
suppressPackageStartupMessages(library(dendextend))
dir <- 'distance_metrics/'
filename <- 'aligned.csv'
my.data <- read.csv(paste(dir, filename, sep=""), header = T, row.names = 1)
my.dist <- as.dist(my.data)
real.clusters <-read.csv("clusters", header = T, row.names = 1)
clustered <- diana(my.dist)
# dend <- colour_branches(???dend, max(real.clusters)???)
plot(dend)

编辑: 另一个示例部分代码

dir <- 'distance_metrics/' # csv in here contains a symmetric matrix
clust.dir <- "clusters/" #csv in here contains a column vector with classes
my.data <- read.csv(paste(dir, filename, sep=""), header = T, row.names = 1)
filename <- 'table.csv'
my.dist <- as.dist(my.data)
real.clusters <-read.csv(paste(clust.dir, filename, sep=""), header = T, row.names = 1)
clustered <- diana(my.dist)
dnd <- as.dendrogram(clustered)

【问题讨论】:

  • 我看到我已经创建了一种使用color_branches 的方法。请看我的回答。

标签: r classification hierarchical-clustering dendrogram dendextend


【解决方案1】:

有些人误解了这个问题,但我会尝试回答: 从我之前的目标被 iris 的例子改写了

clrs <- rainbow(n = 3) # create palette
clrs <- clrs[iris$Species] # assign colors
plot(x = iris$Sepal.Length,y = iris$Sepal.Width,col=clrs) # simple test colors
# cluster
dt <- cbind(iris,clrs)
dt <- dt[sample(x = 1:150,size = 50,replace = F),] # create short dataset for visualization convenience
empty.labl <- gsub("."," ",dt$Species) # create a space vector with length of names intended for  reserve place to future text labels
dst <- dist(x = scale(dt[,1:4]),method = "manhattan")
hcl <- hclust(d = dst,method = "complete")
plot(hcl,hang=-1,cex=1,labels = empty.labl, xlab = NA,sub=NA)
dt <- dt[hcl$order,] # sort rows for  order objects in dendrogramm
text(x = seq(nrow(dt)), y=-.5,labels = dt$Species,srt=90,cex=.8,xpd=NA,adj=c(1,0.7),col=as.character(dt$clrs))

【讨论】:

  • 感谢您的回答,但我在 clusters\edges\lines 上寻找颜色。不仅在刻度\标签名称上。问题是如何使用标签名称选择颜色(例如,按集群中最常见的标签颜色着色)
【解决方案2】:

可以使用dendrapply 在“树状图”对象(只是深度嵌套的列表)上递归设置节点和边缘颜色属性。 cluster 包还具有用于“diana”类对象的as.dendrogram 方法,因此对象类型之间的转换是无缝的。使用您的diana 聚类并从@Edvardoss iris 示例中借用一些代码,您可以按如下方式创建彩色树状图:

library(cluster)
set.seed(999)
iris2 <- iris[sample(x = 1:150,size = 50,replace = F),]
clust <- diana(iris2)
dnd <- as.dendrogram(clust)

## Duplicate rownames aren't allowed, so we need to set the "labels"
## attributes recursively. We also label inner nodes here. 
rectify_labels <- function(node, df){
  newlab <- df$Species[unlist(node, use.names = FALSE)]
  attr(node, "label") <- (newlab)
  return(node)
}
dnd <- dendrapply(dnd, rectify_labels, df = iris2)

## Create a color palette as a data.frame with one row for each spp
uniqspp <- as.character(unique(iris$Species))
colormap <- data.frame(Species = uniqspp, color = rainbow(n = length(uniqspp)))
colormap[, 2] <- c("red", "blue", "green")
colormap

## Now color the inner dendrogram edges
color_dendro <- function(node, colormap){
  if(is.leaf(node)){
    nodecol <- colormap$color[match(attr(node, "label"), colormap$Species)]
    attr(node, "nodePar") <- list(pch = NA, lab.col = nodecol)
    attr(node, "edgePar") <- list(col = nodecol)
  }else{
    spp <- attr(node, "label")
    dominantspp <- levels(spp)[which.max(tabulate(spp))]
    edgecol <- colormap$color[match(dominantspp, colormap$Species)]
    attr(node, "edgePar") <- list(col = edgecol)
  }
  return(node)
}
dnd <- dendrapply(dnd, color_dendro, colormap = colormap)

## Plot the dendrogram
plot(dnd)

【讨论】:

  • 是否有一种通用的方法不通过单词指定颜色(因此不限于预定义的类数)?
  • 当然,您可以只使用 RGB 十六进制格式“#RRGGBB”来指定光谱中的任何颜色。例如,尝试将上面的c("red", "blue", "green") 替换为c("#B44682", "#82B446", "#4682B4")
  • 但这仍然是手工制作的,我不能使用没有硬编码颜色名称(文字或 rgb)的彩虹之类的东西
  • 是的,只需将c("red", "blue", "green") 替换为rainbow(n = length(uniqspp))
【解决方案3】:

您正在寻找的函数是来自dendextend R 包的color_brances,使用参数clusters 和col。以下是一个例子(基于Shaun Wilkinson的示例):

library(cluster)
set.seed(999)
iris2 <- iris[sample(x = 1:150,size = 50,replace = F),]
clust <- diana(iris2)
dend <- as.dendrogram(clust)

temp_col <- c("red", "blue", "green")[as.numeric(iris2$Species)]
temp_col <- temp_col[order.dendrogram(dend)]
temp_col <- factor(temp_col, unique(temp_col))

library(dendextend)
dend %>% color_branches(clusters = as.numeric(temp_col), col = levels(temp_col)) %>% 
   set("labels_colors", as.character(temp_col)) %>% 
   plot

【讨论】:

  • 我认为这是正确的解决方案,但我在真实数据上尝试了它,注意到,当群集不是完全“真实群集”时,它停止。您如何将颜色更改为边缘下代表真实簇的颜色而不是唯一代表的颜色?现实生活数据有噪音,因此不要如此美好地分裂。或者我错过了什么? span>
  • 嗨,你能举一个简单的例子来说明这个问题吗? (我认为这是一个错误)如果是的话 - 您可以将其发布到github.com/talgalili/dendextend/issues span>
  • 你也可以在你的例子中看到它,一些顶部的分支是黑色的,我只是有更多的黑色......
  • 黑色分支是因为它们不属于任何子集群。这是一项功能,而不是错误。
  • 您可以做的是使用color_branchs,k小于您想要的群集数,它将为您的较高分支颜色(但略有不同颜色) span>
猜你喜欢
  • 1970-01-01
  • 2015-07-15
  • 2012-09-02
  • 2018-05-23
  • 2020-06-02
  • 2015-09-16
  • 2017-07-25
  • 2012-08-06
  • 1970-01-01
相关资源
最近更新 更多