简体   繁体   中英

Excluding cells from transparency in heatmap with ggplot

I am trying to generate a heatmap where I can show more than one level of information on each cell. For each cell I would like to show a different color depending on its value in one variable and then overlay this with a transparency (alpha) that shades the cell according to its value for another variable.

Similar questions have been addressed here ( Place 1 heatmap on another with transparency in R ) a and here ( Making a heatmap in R varying both color and transparency ). In both cases the suggestion is to use ggplot and overlay two geom_tiles, one with the colors one with the transparency.

I have managed to overlay two geom_tiles (see code below). However, in my case, the problem is that the shading defined by the transparency (or "alpha") geom_tile also shades some cells that should remain as white or blank according to the colors (or "fill") geom_tile. I would like these cells to remain white even after overlaying the transparency.

#Create sample dataframe
df <- data.frame("x_pos" = c("A","A","A","B","B","B","C","C","C"),
                 "y_pos" = c("X","Y","Z","X","Y","Z","X","Y","Z"),
                 "col_var"= c(1,2,NA,4,5,6,NA,8,9),
                 "alpha_var" = c(7,12,0,3,2,15,0,6,15))

#Convert factor columns to numeric
df$col_var<- as.numeric(df$col_var)
df$alpha_var<- as.numeric(df$alpha_var)

#Cut display variable into breaks
df$col_var_cut <- cut(df$col_var,
                         breaks = c(0,3,6,10),
                         labels = c("cat1","cat2", "cat3"))
#Plot
library(ggplot2)                
ggplot(df, aes (x = x_pos, y = y_pos, fill = col_var_cut, label = col_var)) +
  geom_tile () +
  geom_text() +
  scale_fill_manual(values=(brewer.pal(3, "RdYlBu")),na.value="white") +
  geom_tile(aes(alpha = alpha_var), fill ="gray29")+
  scale_alpha_continuous("alpha_var", range=c(0,0.7), trans = 'reverse')+
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))          

I would like cells "AZ" and "CX" in the heatmap resulting from the code above to be colored white instead of grey such that the alpha transparency doesn't apply to them. In my data, these cells have NA in the color variable (col_var) and can have a value of NA or 0 (as in the example code) in the transparency/alpha variable (alpha_var).

If this is not possible, then I would like to know whether there are other options to display both variables in a heatmap and keep the NA cells in the col_var white? I am happy to use other packages or alternative heatmap layouts such as those where the size of each cell or the thickness of its border vary according to the values the alpha_var. However, I am not sure how I could achieve this either.

Thanks in advance and my apologies for the cumbersome bits in the example code (I am still learning R and this is my first time asking questions here).

You were not far. See below for a possible solution. The first plot shows an implementation of adding transparency within the geom_tile call itself - note I removed the trans = reverse specification from your plot.

Plot 2 just adds back the white tiles on top of the other plot - simple hack which you will often find necessary when wanting to plot certain data points differently.

Note I have added a few minor comments to your code below.

# creating your data frame with better name - df is a base R function and not recommended as example name. 
# Also note that I removed the quotation marks in the data frame call - they were not necessary. I also called as.numeric directly. 
mydf <- data.frame(x_pos = c("A","A","A","B","B","B","C","C","C"), y_pos = c("X","Y","Z","X","Y","Z","X","Y","Z"), col_var= as.numeric(c(1,2,NA,4,5,6,NA,8,9)), alpha_var = as.numeric(c(7,12,0,3,2,15,0,6,15)))

mydf$col_var_cut <- cut(mydf$col_var, breaks = c(0,3,6,10), labels = c("cat1","cat2", "cat3"))

#Plot

library(tidyverse) 
library(RColorBrewer) # you forgot to add this to your reprex

ggplot(mydf, aes (x = x_pos, y = y_pos, fill = col_var_cut, label = col_var)) +
  geom_tile(aes(alpha = alpha_var)) +
  geom_text() +
  scale_fill_manual(values=(brewer.pal(3, "RdYlBu")), na.value="white")
#> Warning: Removed 2 rows containing missing values (geom_text).


# a bit hacky for quick and dirty solution. Note I am using dplyr::filter from the tidyverse

ggplot(mapping = aes(x = x_pos, y = y_pos, fill = col_var_cut, label = col_var)) +
  geom_tile(data = filter(mydf, !is.na(col_var))) +
  geom_tile(data = filter(mydf, !is.na(col_var)), aes(alpha = alpha_var), fill ="gray29")+
  geom_tile(data = filter(mydf, is.na(col_var)), fill = 'white') +
  geom_text(data = mydf) + 
  scale_fill_manual(values = (brewer.pal(3, "RdYlBu"))) +
  scale_alpha_continuous("alpha_var", range=c(0,0.7), trans = 'reverse')  
#> Warning: Removed 2 rows containing missing values (geom_text).

Created on 2019-07-04 by the reprex package (v0.2.1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM