Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overlay of color plots with 2 color scales ggplot2

Tags:

plot

r

ggplot2

Attempting to overlay color plots (something like below) using ggplot2

Red + Green giving Yellow in the 3rd column

Trying to use geom_tile but ggplot doesnt allow me to add 2 color scales. Here is an example code.

df <- data.frame(expand.grid(1:5,1:5))
df$z1 <- runif(nrow(df))
df$z2 <- runif(nrow(df))
g1 <- ggplot(df,aes(Var1,Var2)) + theme_bw()
#layer 1
g11 <- g1  + geom_tile(aes(fill=z1),alpha=0.5) + scale_fill_gradient(low="white", high="red")
#layer 2
g12 <- g1  + geom_tile(aes(fill=z2),alpha=0.5) + scale_fill_gradient(low="white", high="green")
g11
g12

One way to possible do this is to make the 2 layers as different groups. But the outcome just doesn't look intuitive.

mdf=melt(df,'id'=1:2)
g2 <- ggplot(mdf,aes(Var1,Var2,fill = factor(variable),alpha = value)) + 
     geom_tile() + scale_fill_manual(values = c('red','green')) + theme_bw()
g2

best outcome i could come up with

like image 514
d2a2d Avatar asked Jan 02 '15 07:01

d2a2d


1 Answers

You're really close: just don't divide z1 and z2 by 2.

There is another issue to consider though. If z1 and z2 are not on the same scale, should you use a common scale for both, or should you scale them independently? The result is (can be) different, as illustrated below.

gg.overlay <- function(df) {  # produces 2 color channels and the overlay
  require(ggplot2)
  require(gridExtra)
  gg.z1 <- ggplot(df, aes(x,y))+
    geom_tile(fill=rgb(red=df$z1.scale,green=0,blue=0))+
    scale_x_continuous(expand=c(0,0))+
    scale_y_continuous(expand=c(0,0))+
    coord_fixed()

  gg.z2 <- ggplot(df, aes(x,y))+
    geom_tile(fill=rgb(red=0,green=df$z2.scale,blue=0))+
    scale_x_continuous(expand=c(0,0))+
    scale_y_continuous(expand=c(0,0))+
    coord_fixed()

  gg <- ggplot(df, aes(x,y))+
    geom_tile(fill=rgb(red=df$z1.scale,green=df$z2.scale,blue=0))+
    scale_x_continuous(expand=c(0,0))+
    scale_y_continuous(expand=c(0,0))+
    coord_fixed()

  library(gridExtra)
  grid.arrange(gg.z1, gg.z2, gg, ncol=3)
}

Using an example slightly closer to the image in your question:

library(mvtnorm)  # just for this example
df    <- expand.grid(x=seq(-3,3,len=100),y=seq(-3,3,len=100))
df$z1 <- with(df,dmvnorm(cbind(x,y),mean=c(0,0),sigma=matrix(c(1,-1,-1,2),nc=2)))
df$z2 <- with(df,3*dmvnorm(cbind(x,y),mean=c(0,0),sigma=matrix(c(1,0,0,1),nc=2)))

# scale z1 and z2 together
max.z <- with(df,max(z1,z2))
min.z <- with(df,min(z1,z2))
df$z1.scale <- with(df, (z1-min.z)/(max.z-min.z))
df$z2.scale <- with(df, (z2-min.z)/(max.z-min.z))
gg.overlay(df)

# scale z1 and z2 separately
df$z1.scale <- with(df, (z1-min(z1))/diff(range(z1)))
df$z2.scale <- with(df, (z2-min(z2))/diff(range(z2)))
gg.overlay(df)

In the first case the reds are muted because the z1 intensities are lower than the z2 intensities. In the second case we scale them separately, so the reds are more vibrant. It's not clear which is the "correct" method.

like image 131
jlhoward Avatar answered Oct 17 '22 13:10

jlhoward