改变plot.dendrogram中的叶子颜色,就像使用package ape的plot.phylo一样

时间:2013-04-17 14:25:36

标签: r dendrogram ape col dendextend

我试图用与使用包'ape'绘制树的相同'风格'来绘制凝聚聚类(UPGMA与Agnes)的结果。我在下图中包含了一个简单的例子 Figure 1. A simple example of the final output required

关键问题是我希望能够根据叶子标签中的图案为树形图的叶子着色。我尝试了两种方法:要么使用hc2Newick,要么使用Joris Meys的代码作为对Change Dendrogram leaves的回答。两者都没有给出令人满意的结果。可能是我还没有完全理解树形图的构建方式。可以在https://www.dropbox.com/s/gke9qnvwptltkky/abundance.agnes.ave上找到abundance.agnes.ave对象的ASCII保存(从运行的agnes中存储)。

当我使用第一个选项(来自bioconductor的hc2Newick包中的ctc)时,使用此代码时会得到下图:

write(hc2Newick(as.hclust(abundance.agnes.ave)),file="all_samples_euclidean.tre")
eucltree<-read.tree(file="all_samples_euclidean.tre")
eucltree.laz<-ladderize(eucltree,FALSE)
tiplabs<-eucltree$tip.label
numbertiplabs<-length(tiplabs)
colourtips<-rep("green",numbertiplabs)
colourtips[grep("II",tiplabs)]<-"red"
plot(eucltree.laz,tip.color=colourtips,adj=1,cex=0.6,use.edge.length=F)
add.scale.bar()

Using plot.phylo

这显然不太理想,情节的“对齐”并非我想要的。我认为这与分支长度计算有关,但我没有最模糊的想法如何解决这个问题。当然,与colLab函数的结果相比,它看起来更像我想要报告的树形图样式。此外,在上面的代码中使用use.edge.length=T确实给出了一个未正确“对齐”的聚类: Plot.phylo with branch length

第二种方法使用Joris Meys的colLab函数和下面的代码给出了下一个图

clusDendro<-as.dendrogram(as.hclust(abundance.agnes.ave))
labelColors<-c("red","green")
clusMember<-rep(1,length(rownames(abundance.x)))
clusMember[grep("II",rownames(abundance.x))]<-2
names(clusMember)<-rownames(abundance.x)

colLab <- function(n)
{
  if(is.leaf(n)) {
    a <- attributes(n)
    # clusMember - a vector designating leaf grouping
    # labelColors - a vector of colors for the above grouping
    labCol <- labelColors[clusMember[which(names(clusMember) == a$label)]]
    attr(n, "nodePar") <- c(a$nodePar, lab.col = labCol)
  }
  n
}

clusDendro<-dendrapply(clusDendro, colLab)
plot(clusDendro,horiz=T,axes=F)

Using colLab 这个情节越来越接近我想要的,但是我不知道为什么圆圈上会出现空心圆以及如何将它们移除。

非常感谢任何帮助。

亲切的问候,

FM

2 个答案:

答案 0 :(得分:2)

此功能现在可在名为“dendextend”的新软件包中使用,该软件包完全针对此类内容构建。

您可以在以下网址的“使用情况”部分中看到该套餐的演示文稿和插图中的许多示例:https://github.com/talgalili/dendextend

在以下SO问题中回答了一个几乎完全正确的问题:

https://stackoverflow.com/a/18832457/256662

答案 1 :(得分:0)

我很久以前就编写了这段代码,看起来机制中有些东西发生了变化。

我使用的plot.dendrogram函数有一个参数nodePar。自从我上次使用该函数以来,行为已经改变,虽然这通常用于内部节点,但它显然也对外部节点有影响。根据帮助文件,pch的默认值现在为1:2

因此,您需要在添加到pch=NA函数中的外部节点的属性中专门指定colLab。尝试适应它:

colLab <- function(n)
{
  if(is.leaf(n)) {
    a <- attributes(n)
    # clusMember - a vector designating leaf grouping
    # labelColors - a vector of colors for the above grouping
    labCol <- labelColors[clusMember[which(names(clusMember) == a$label)]]

    attr(n, "nodePar") <- 
        if(is.list(a$nodePar)) c(a$nodePar, lab.col = labCol,pch=NA) else
                               list(lab.col = labCol,pch=NA)
  }
  n
}

在我的机器上,解决了这个问题。

或者,您可以查看use.edge.length包中函数plot.phylo的参数ape。您将其设置为FALSE,但根据您的说明,我相信您希望将其设置为默认值TRUE

编辑:为了使函数更通用,最好将labelColorsclusMember作为参数添加到函数中。我的快速解决方案并不是干净代码的最好例子......

还要忘记我对使用边长的说法。 ape包将其解释为真正的树形图,将use.edge.length放到TRUE会将边长转换为进化时间。因此,树状图的“怪异”概述。

另请注意,如果treeleaf没有nodePar属性,使用c()函数添加额外参数将导致不良影响:如果添加例如lab.cex=0.6c()函数将创建向量而不是列表,并且只要参数列表中有字符值,就将lab.cex的值转换为字符。在这种情况下,这将是颜色的名称,这解释了您在评论中谈到的错误。