1

I'm building a visualisation of a dataset using the geom_tile function in ggplot2. I'm almost satisfied with it, however I'd like to add a particular legend to it, but I haven't been able to find a suitable method for this. I'll explain what I mean exactly later on in the post.

Here's the code that I'm currently using, it's probably a huge mess as I'm not proficient in R and basically generated this by trial and error. If anyone is willing to clean it up, knock yourself out :-) .

#Read source data
meta <- read.csv("Dropbox/meta_censored.csv")

#import libraries  
library("ggplot2")
library("plyr")
library("reshape2")
library("scales")
library("grid")

#transform and rescale data in prep for later steps
meta.m <- melt(meta)
meta.s <- ddply(meta.m, .(variable), transform,
                rescale = scale(value))


#generate categories to sort conditions by colour
meta.s$Category <- meta.s$variable
levels(meta.s$Category) <-
  list("1_early" = c("X1", "X2"),
       "2_early" = c("X3", "X4", "X5", "X6", "X7"),
       "1_late" = c("X10", "X17"),
       "2_late" = c("X8", "X9", "X11", "X12", "X14", "X15", "X16"),
       "3_late" = "X13",
       "4_late" = c("X18", "X19"))

#define colours per category
meta.s$rescaleoffset <- meta.s$rescale + 100*(as.numeric(meta.s$Category)-1)
scalerange <- range(meta.s$rescale)
gradientends <- scalerange + rep(c(0,100,200,300,400,500), each = 2)
colorends <- c("white", "red", "white", "green", "white", "red", "white", "green", "white", "orange", "white", "purple")

#reorder by category
meta.s$variable2 <- reorder(meta.s$variable, as.numeric(meta.s$Category))

#reverse y axis labels (were z-a, now a-z)
flevels <- levels(meta.s$Param)
flevels <- rev(flevels)

#x axis annotation variables
text_early <- textGrob("Early", gp=gpar(fontsize = 5, fontface = "bold", col = "red"))
text_late <- textGrob("Late", gp=gpar(fontsize = 5, fontface = "bold", col = "red"))

#plot heatmap
p <- ggplot(meta.s, aes(variable2, Param)) +
  geom_tile(aes(fill = rescaleoffset), colour = "lightgrey") + 
  #add line to seperate early from late
  geom_vline(xintercept = 7.5) +
  scale_fill_gradientn(colours = colorends, values = rescale(gradientends)) +
  scale_x_discrete("", expand = c(0, 0)) +
  scale_y_discrete("", limits = flevels, expand = c(0, 0)) +
  theme_grey(base_size = 5) + 
  theme(legend.position = "right",
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, size = 5, vjust = 0, face = "bold"),
        plot.margin = unit(c(1,1,2,1), "lines")) +
  annotation_custom(text_early, xmin = 0, xmax = 8, ymin=168.5, ymax = 168.5) +
  annotation_custom(text_late, xmin = 8, xmax = 19, ymin=168.5, ymax = 168.5)

gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

Basically, I'm trying to show values per object in column Param by each value on the x axis. Each value on the x axis represents a different study, with different experimental conditions. I have tried grouping them using this thread, and each group gets a different colour.

Now what I ideally want is that the legend displays the respective solid colour for each category, and not an overall gradient based on the value of each of the cells. Of course it doesn't need to be a legend produced with ggplot2, any other method is accepted as long as it does the trick.

Thanks in advance!

Community
  • 1
  • 1
plinders
  • 23
  • 4

1 Answers1

0

You can include shape = Category (which won't change the appearance of the plot as it has no effect in geom_tile) and then use override.aes to get the colours for each Category. If you only want 4 categories you can use substr to define the fill colour based on the number (1st element). In order to remove the gradient legend you can add guide = FALSE to scale_fill_gradientn:

ggplot(meta.s, aes(variable2, Param)) +
  geom_tile(aes(fill = rescaleoffset, shape = substr(Category, 1, 1)), colour = "lightgrey", show.legend = TRUE) + 
  #add line to seperate early from late
  geom_vline(xintercept = 7.5) +
  scale_fill_gradientn(colours = colorends, values = rescale(gradientends), guide = FALSE) +
  scale_x_discrete("", expand = c(0, 0)) +
  scale_y_discrete("", limits = flevels, expand = c(0, 0)) +
  theme_grey(base_size = 5) + 
  theme(legend.position = "right",
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, size = 5, vjust = 0, face = "bold"),
        plot.margin = unit(c(1,1,2,1), "lines")) +
  annotation_custom(text_early, xmin = 0, xmax = 8, ymin=168.5, ymax = 168.5) +
  annotation_custom(text_late, xmin = 8, xmax = 19, ymin=168.5, ymax = 168.5) +
  guides(shape = guide_legend("Category", override.aes = list(fill = c("red", "green", "orange", "purple"))))

enter image description here

erc
  • 10,113
  • 11
  • 57
  • 88