Reproducing lattice dendrogram graph with ggplot2
Asked Answered
S

4

36

Is this possible to reproduce this lattice plot with ggplot2?

library(latticeExtra)
data(mtcars)
x  <- t(as.matrix(scale(mtcars)))
dd.row <- as.dendrogram(hclust(dist(x)))
row.ord <- order.dendrogram(dd.row)

dd.col <- as.dendrogram(hclust(dist(t(x))))
col.ord <- order.dendrogram(dd.col)

library(lattice)

levelplot(x[row.ord, col.ord],
      aspect = "fill",
      scales = list(x = list(rot = 90)),
      colorkey = list(space = "left"),
      legend =
      list(right =
           list(fun = dendrogramGrob,
                args =
                list(x = dd.col, ord = col.ord,
                     side = "right",
                     size = 10)),
           top =
           list(fun = dendrogramGrob,
                args =
                list(x = dd.row,
                     side = "top",
                     size = 10))))

enter image description here

Serai answered 13/7, 2011 at 1:32 Comment(3)
have you tried anything thus far?Germin
my guess: possible (everything is possible), not easy. Someone has done some phylogenies in ggplot2 and there may be other code for drawing dendrograms. You probably have to do the pieces and put them together with grid graphics ... Actually, since you've already got dendrogramGrobs, you may be able to make the middle piece with geom_tile and then put the pieces together with functions from ggExtra and gridExtra ...Hovel
@BenBolker As you say, everything is possible. And in this case it has just become a little bit easier. See my answer: #6673662Willwilla
W
53

EDIT

From 8 August 2011 the ggdendro package is available on CRAN Note also that the dendrogram extraction function is now called dendro_data instead of cluster_data


Yes, it is. But for the time being you will have to jump through a few hoops:

  1. Install the ggdendro package (available from CRAN). This package will extract the cluster information from several types of cluster methods (including Hclust and dendrogram) with the express purpose of plotting in ggplot.
  2. Use grid graphics to create viewports and align three different plots.

enter image description here

The code:

First load the libraries and set up the data for ggplot:

library(ggplot2)
library(reshape2)
library(ggdendro)

data(mtcars)
x <- as.matrix(scale(mtcars))
dd.col <- as.dendrogram(hclust(dist(x)))
col.ord <- order.dendrogram(dd.col)

dd.row <- as.dendrogram(hclust(dist(t(x))))
row.ord <- order.dendrogram(dd.row)

xx <- scale(mtcars)[col.ord, row.ord]
xx_names <- attr(xx, "dimnames")
df <- as.data.frame(xx)
colnames(df) <- xx_names[[2]]
df$car <- xx_names[[1]]
df$car <- with(df, factor(car, levels=car, ordered=TRUE))

mdf <- melt(df, id.vars="car")

Extract dendrogram data and create the plots

ddata_x <- dendro_data(dd.row)
ddata_y <- dendro_data(dd.col)

### Set up a blank theme
theme_none <- theme(
  panel.grid.major = element_blank(),
  panel.grid.minor = element_blank(),
  panel.background = element_blank(),
  axis.title.x = element_text(colour=NA),
  axis.title.y = element_blank(),
  axis.text.x = element_blank(),
  axis.text.y = element_blank(),
  axis.line = element_blank()
  #axis.ticks.length = element_blank()
)

### Create plot components ###    
# Heatmap
p1 <- ggplot(mdf, aes(x=variable, y=car)) + 
  geom_tile(aes(fill=value)) + scale_fill_gradient2()

# Dendrogram 1
p2 <- ggplot(segment(ddata_x)) + 
  geom_segment(aes(x=x, y=y, xend=xend, yend=yend)) + 
  theme_none + theme(axis.title.x=element_blank())

# Dendrogram 2
p3 <- ggplot(segment(ddata_y)) + 
  geom_segment(aes(x=x, y=y, xend=xend, yend=yend)) + 
  coord_flip() + theme_none

Use grid graphics and some manual alignment to position the three plots on the page

### Draw graphic ###

grid.newpage()
print(p1, vp=viewport(0.8, 0.8, x=0.4, y=0.4))
print(p2, vp=viewport(0.52, 0.2, x=0.45, y=0.9))
print(p3, vp=viewport(0.2, 0.8, x=0.9, y=0.4))
Willwilla answered 13/7, 2011 at 8:16 Comment(17)
very nice. Would be nice to (1) move the legend out of the way somewhere and (2) expand the geom_tile() so it filled the whole panel (I think these are both doable, #2 internally and #1 with ggExtra tricks ...)Hovel
@BenBolker, yes indeed. This is the beauty of ggplot, isn't it? Once the data is in the desired format, one can manipulate all of the plot format...Willwilla
@Andrie: When this R package will be available to install? Actually I want to use this package but don't know how to build this after downloading. ThanksSerai
@Serai The ggdendro package is now available on CRAN: cran.r-project.org/web/packages/ggdendro/index.htmlWillwilla
Is this possible to display the variable labels and car label under the corresponding segments of the dendrogram? Thanks for your help.Serai
This is awesome! Wish there was a function for this! I was wondering if there was a way to get the dendogram size to match the tile plot size? Manually adjusting the viewport size and location is tedious and does not work perfectly, but it should be possible to do it from the info within the plots :(#13867825 and #13295452)Dissimulation
there is something wrong with the above code. > print(p2, vp=viewport(0.52, 0.2, x=0.45, y=0.9)) Error in eval(expr, envir, enclos) : object 'x0' not found > print(p3, vp=viewport(0.2, 0.8, x=0.9, y=0.4)) Error in eval(expr, envir, enclos) : object 'x0' not foundProtestantism
I have the same problem as @eastafri. Did we miss something here?Waring
Wait, I got it. Must be connected with the usage of the new dendro_data function. Instead of x0 and x1 you need to use x and xend. Same for y.Waring
@Waring Thank you for identifying that fix. I have updated the answer to reflect this, and also to conform to the current release of ggplot2, i.e. no theme warnings.Willwilla
Thanks for the corrections. One also needs to load the gridExtra package. Additionally my dendrogram along the x-axis is not properly aligned. anyone else who got something like that?Protestantism
You're welcome. :-) Yes, you also need gridExtra, and you have to align the dendrogram manually with the viewport options. I had to tweak mine as well from the example. By the way, does anyone know how you get the dendrogram closer to the heatmap? The distance is a bit wide and when I try to close it I loose data points from the heatmap.Waring
Hi, I have another question about this... Would it be possible to add another figure into that plot? For a publication, I need to combine a histogram and such a heat map in one...Waring
@Waring Yes, use grid viewports. Look here for inspiration: #8112708Willwilla
I would have loved to use grid.arrange instead! But I've more or less figured it out with viewports now, thanks.Waring
Is there a way to align the dendrograms without manually setting the viewport sizes, like @EtienneLow-Décarie is suggesting? Reviving an old thread here, but can't seem to find an answer out there.Tainataint
Recent versions of ggdendro seem to contain a theme_dendro object, which you can use instead of defining a theme_none as in the example. This should shorten the code.Jat
P
6

As Ben says, everything is possible. Some work to support dendrograms has been done. Andrie de Vries has made a fortify method of tree objects. However, the resulting graphic is not pretty as you can see.

The tile would be easy to do. For the dendrogram I would inspect plot.dendrogram (using getAnywhere) to see how the coordinates for the segments are calculated. Extract those coordinates and use geom_segment to plot the dendrogram. Then use viewports to plot the tiles and the dendrogram together. Sorry I can't give a example, it's a lot of work and it's too late.

I hope this helps

Cheers

dendrogram

Perreault answered 13/7, 2011 at 2:51 Comment(1)
+1 for digging up code that I wrote a long, long time ago. Not pretty, as you say...Willwilla
O
4

Doubtful. I do not see any functions in the Index for ggplot2 that would suggest support for dendrograms, and when this blogger put together a set of translations of the illustrations in Sarkar's Lattice book, he was unable to get a ggplot dendrogram legend:

http://learnr.wordpress.com/2009/08/10/ggplot2-version-of-figures-in-lattice-multivariate-data-visualization-with-r-part-9/

Overhang answered 13/7, 2011 at 2:0 Comment(2)
I think some people have hacked together some solutions that at least would be good starting points: see here, here and possibly this might be of some use as well.Settera
@DWin Never say never. See my answer: #6673662Willwilla
W
1

These links provide a solution for heatmaps with dendrograms in ggplot2:

https://gist.github.com/chr1swallace/4672065

https://github.com/chr1swallace/random-functions/blob/master/R/ggplot-heatmap.R

and also this one:

Align ggplot2 plots vertically

Wingate answered 2/4, 2014 at 12:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.