rggplot2geom-raster

Plot multiple layers with ggplot2


I am trying to plot two data.frame as two layers using ggplot2 "geom_raster" function. The top layer contains NA values that are set to "transparent" in order to make the underneath layer visible. As the scale_fill_xxx function can't be used twice, I've tried the following code (based on this post : ggplot2 - using two different color scales for overlayed plots) :

library(ggplot2)

df1 <- data.frame(x=rep(c(1,2,3),times=3), y=c(1,1,1,2,2,2,3,3,3), data= c(NA,4,9,NA,2,7,NA,NA,3))
df2 <- data.frame(x=rep(c(1,2,3),times=3), y=c(1,1,1,2,2,2,3,3,3), data= c(1,NA,NA,2,NA,NA,1,2,NA))

ggplot() + 
geom_raster(data=df1, aes(y= y, x= x, fill= data)) + 
scale_fill_gradientn(name="df1", colours=c("red", "blue"), na.value = "transparent") + 
geom_raster(data= df2, aes(y= y, x= x, colour= as.factor(data))) + 
scale_colour_manual(values = c("green", "black"), name= "df2", labels= c("Class 1", "Class 2"), na.value="transparent")

The thing is that the "colour" / "scale_colour_manual" solution does not return what I expect (it returns a dark grey plot instead). I would like the df1 "data" column to be represented on a red to blue scale (NA's should be transparent) and the df2 "data" column to be represented according to class number ("1"=green and "2"=black).

Could anyone help me to understand what's wrong with my procedure?


Solution

  • Here is a solution :

    df3 = merge(df1, df2, by = c("x","y"))
    names(df3)[names(df3) == "data.x"] <- "data.1"
    names(df3)[names(df3) == "data.y"] <- "data.2"
    df3$data = df3$data.1
    df3$data[is.na(df3$data)] = df3$data.2[is.na(df3$data)]
    
    myGrad <- colorRampPalette(c('blue','red')) # color gradient
    min_value = min(df3$data[df3$data >2]) # minimum value except 1 and 2
    max_value = max(df3$data) # maximum value 
    param = max_value - min_value + 1 # number of colors in the gradient
    
    
    ggplot(df3, aes(x, y, fill = data)) + geom_raster() + 
    scale_fill_gradientn(colours=c("green","black", myGrad(param)), 
    values = rescale(c(1, 2, seq(min_value, max_value, 1))), na.value = "transparent")
    

    3x3 picture

    I guess you will use this plot with higher values and ranges, I tried with a 5x5 matrix:

    set.seed(123)
    df4 = data.frame(x=rep(c(1,2,3,4,5),5), y=c(rep(1,5), rep(2,5), rep(3,5), rep(4,5), rep(5,5)), 
    data = sample(c(1:20), 25, prob = c(0.2,0.2,rep(0.6/18,18)), replace = T))
    min_value = min(df4$data[df4$data >2])
    max_value = max(df4$data)
    param = max_value - min_value + 1 
    
    ggplot(df4, aes(x, y, fill = data)) + geom_raster() + 
    scale_fill_gradientn(colours=c("green","black", myGrad(param)), 
    values = rescale(c(1, 2, seq(min_value, max_value, 1))), na.value = "transparent")
    

    enter image description here