Creating a legend for a dendrogram with coloured leaves in r
Asked Answered
S

2

5

I have coloured the leaves in a dendrogram as follows

require(graphics)

dm <- hclust(dist(USArrests[1:5,]), "ave")

df<-data.frame("State"=c("Alabama","Alaska","Arizona","Arkansas","California"),   "Location"=c("South","North","West","South","West"))


color.sites<-function(dm){
    dend<-as.dendrogram(dm)
    plot(dend)

    cols <- attributes(dend)
    df$ColorGroups <- factor(df$Location)

    #Set colour pallette
    Location.Pal <- rainbow(nlevels(df$ColorGroups), s=0.9,v=0.9,start=0.1,end=0.9,alpha=1)

    colorleaves <- function (n) {
    # only apply to "leaves" in other words the labels
    if(is.leaf(n)) { 
        i <- which(df$State == attr(n,"label"))
        col.lab  <- Location.Pal[[unclass(df$ColorGroups[[i]])]]
        a <- attributes(n)
        attr(n, "nodePar") <- c(a$nodePar, list(lab.col = col.lab))
    }
    n
}

xx <- dendrapply(dend, colorleaves)

plot(xx, cex=3, cex.main=2, cex.lab=5, cex.axis=1, mar=c(3,3,3,3), main="Title")
}

color.sites(dm)

enter image description here

I would like to: 1) add a legend explaining the colours (i.e. Orange = North) 2) make the leaf labels larger and bolder (cex.lab does not seem to do the job) 3) create a color palette that has sharply contrasting colour (rainbow,heat.colors etc all seem to blend together when there are many leaves and colours in the dendrogram.

Any advice is greatly appreciated !

Strigose answered 15/8, 2012 at 10:37 Comment(2)
Please try to limit yourself to 1 question per post. Multiple questions is fine, just link them together to show they are related.Leija
Will keep this in mind for future post.Strigose
H
6

If you already know how to use and tweak ggplot2 graphics, another solution will be to use @Andrie ggdendro package

library(ggplot2)
library(ggdendro)

dm <- hclust(dist(USArrests[1:5,]), "ave")

df <- data.frame(State = c("Alabama","Alaska","Arizona","Arkansas","California"),
                 Location = c("South","North","West","South","West"))


hcdata<- dendro_data(dm, type="rectangle")

hcdata$labels <- merge(x = hcdata$labels, y = df,  by.x = "label", by.y = "State")


ggplot() +
 geom_segment(data=segment(hcdata), aes(x=x, y=y, xend=xend, yend=yend)) +
 geom_text(data = label(hcdata), aes(x=x, y=y, label=label, colour = Location, hjust=0), size=3) +
 geom_point(data = label(hcdata), aes(x=x, y=y), size=3, shape = 21) +
 coord_flip() +
 scale_y_reverse(expand=c(0.2, 0)) +
 scale_colour_brewer(palette = "Dark2") + 
 theme_dendro() 

enter image description here

Herr answered 15/8, 2012 at 10:37 Comment(3)
+1 This is probably the first time on SO that somebody (other than myself) posts a solution using ggdendroCrowberry
@Crowberry : Thank's again for ggdendro !! it's a great package to manage tree like structure and plot them using the popular ggplot2Herr
@Dickoa Thank you for making me aware of the ggdendro package. I need the height to be displayed as in my example and also I need the orientation of the dendrogram to remain the same. Excluding the coord_flip() causes the dendrogram to be upside down though. How can I use ggdendro but have the orientation be the same as in my example and also have the height shown on the y axis? Thanks again.Strigose
L
4
  1. Use legend()

    cols <- c("orange","forestgreen")
    legend("topright", legend = c("North","South"),
           fill = cols, border = cols, bty = "n")
    
  2. I don't believe you can, without hacking stats:::plot.dendrogram() as the labels are drawn with text() and graphical parameters are not passed on to that function. The relevant code in stats:::plot.dendrogram() is:

    if (!is.null(et <- attr(x, "edgetext"))) {
        my <- mean(hgt, yTop)
        if (horiz) 
            text(my, x0, et)
        else text(x0, my, et)
    }
    

    Copy the entire function source into an editor and edit it to do what you want, then assign it to your own function object and use it. If it fails because it can't find functions (they may be unexported from namespaces, find out which namespace it is an prepend the offending function with ns::: where ns is the relevant namespace.

  3. Try the RColorBrewer package for one option to choose categorical palettes.

Leija answered 15/8, 2012 at 11:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.