Search code examples
rggplot2

Create heatmap with values from matrix in ggplot2


I've seen heatmaps with values made in various R graphics systems including lattice and base like this:

enter image description here

I tend to use ggplot2 a bit and would like to be able to make a heatmap with the corresponding cell values plotted. Here's the heat map and an attempt using geom_text:

library(reshape2, ggplot2)
dat <- matrix(rnorm(100, 3, 1), ncol=10)
names(dat) <- paste("X", 1:10)
dat2 <- melt(dat, id.var = "X1")
p1 <- ggplot(dat2, aes(as.factor(Var1), Var2, group=Var2)) +
    geom_tile(aes(fill = value)) +
    scale_fill_gradient(low = "white", high = "red") 
p1

#attempt
labs <- c(apply(round(dat[, -2], 1), 2, as.character))
p1 +  geom_text(aes(label=labs), size=1)

Normally I can figure out the x and y values to pass but I don't know in this case since this info isn't stored in the data set. How can I place the text on the heatmap?


Solution

  • Key is to add a row identifier to the data and shape it "longer".

    edit Dec 2022 to make code reproducible with R 4.2.2 / ggplot2 3.4.0 and reflect changes in tidyverse semantics

    library(ggplot2)
    library(tidyverse)
    dat <- matrix(rnorm(100, 3, 1), ncol = 10)
    ## the matrix needs names
    names(dat) <- paste("X", 1:10)
    
    ## convert to tibble, add row identifier, and shape "long"
    dat2 <-
      dat %>%
      as_tibble() %>%
      rownames_to_column("Var1") %>%
      pivot_longer(-Var1, names_to = "Var2", values_to = "value") %>%
      mutate(
        Var1 = factor(Var1, levels = 1:10),
        Var2 = factor(gsub("V", "", Var2), levels = 1:10)
      )
    #> Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if
    #> `.name_repair` is omitted as of tibble 2.0.0.
    #> ℹ Using compatibility `.name_repair`.
    
    ggplot(dat2, aes(Var1, Var2)) +
      geom_tile(aes(fill = value)) +
      geom_text(aes(label = round(value, 1))) +
      scale_fill_gradient(low = "white", high = "red")
    

    Created on 2022-12-31 with reprex v2.0.2