1

I would like to plot with gglot's geom_raster a 2D plot with 2 different gradients, but I do not know if there is a fast and elegant solution for this and I am stuck.

The effect that I would like to see is the overlay of multiple geom_raster, essentially. Also, I would need a solution that scales to N different gradients; let me give an example with N=2 gradients which is easier to follow.

I first create a 100 x 100 grid of positions X and Y

# the domain are 100 points on each axis
domain = seq(0, 100, 1) 

# the grid with the data
grid = expand.grid(domain, domain, stringsAsFactors = FALSE)
colnames(grid) = c('x', 'y')

Then I compute one value per grid point; imagine something stupid like this

grid$val = apply(grid, 1, function(w) { w['x'] * w['y'] }

I know how to plot this with a custom white to red gradient

ggplot(grid, aes(x = x, y = y)) +
  geom_raster(aes(fill = val), interpolate = TRUE) +
  scale_fill_gradient(
      low = "white", 
      high = "red", aesthetics = 'fill')

But now imagine I have another value per grid point

grid$second_val = apply(grid, 1, function(w) { w['x'] * w['y'] + runif(1) }

Now, how do I plot a grid where each position "(x,y)" is coloured with an overlay of:

  • 1 "white to red" gradient with value given by val
  • 1 "white to blue" gradient with value given by second_val

Essentially, in most applications val and second_val will be two 2D density functions and I would like each gradient to represent the density value. I need two different colours to see the different distribution of the values.

I have seen this similar question but don't know how to use that answer in my case.

qubert
  • 83
  • 5
  • Related: https://stackoverflow.com/questions/24078774/overlay-two-ggplot2-stat-density2d-plots-with-alpha-channels – pogibas Oct 27 '18 at 15:02
  • This seems relevant too: https://github.com/jschoeley/tricolore – Jon Spring Oct 27 '18 at 15:08
  • Thanks for the links. I am looking at the first of the two so far, but I need to understand how to use my computed values instead of the `stat_2d` density value as they are not the same thing. – qubert Oct 27 '18 at 16:28
  • Possible duplicate of [Plotting multiple layers with geom\_raster() or geom\_tile or geom\_rect()](https://stackoverflow.com/questions/43395219/plotting-multiple-layers-with-geom-raster-or-geom-tile-or-geom-rect) – Brian D Aug 26 '19 at 14:41

1 Answers1

1

@Axeman's answer to my question, which you linked to, applies directly the same to your question.

Note that scales::color_ramp() uses values between 0 and 1, so normalize val and second_val between 0, 1 before plotting

grid$val_norm <- (grid$val-min(grid$val))/diff(range(grid$val))
grid$second_val_norm <- (grid$second_val-min(grid$second_val))/diff(range(grid$second_val))

Now plot using @Axeman's answer. You can plot one later as raster, and overlay the second with annotate. I have added transparency (alpha=.5) otherwise you'll only be able to see the second layer.:

ggplot(grid, aes(x = x, y = y)) +
  geom_raster(aes(fill=val)) + 
  scale_fill_gradient(low = "white", high = "red", aesthetics = 'fill') + 
  annotate(geom="raster", x=grid$x, y=grid$y, alpha=.5,
           fill = scales::colour_ramp(c("transparent","blue"))(grid$second_val_norm))

Or, you can plot both layers using annotate().

# plot using annotate()
ggplot(grid, aes(x = x, y = y)) +
  annotate(geom="raster", x=grid$x, y=grid$y, alpha=.5,
           fill = scales::colour_ramp(c("transparent","red"))(grid$val_norm)) +
  annotate(geom="raster", x=grid$x, y=grid$y, alpha=.5,
           fill = scales::colour_ramp(c("transparent","blue"))(grid$second_val_norm))
Brian D
  • 2,570
  • 1
  • 24
  • 43