22

Changing the upper limits for scale_fill_gradient2 also effects the colorscaling for values < 0 as the color distribution around 0 seems to be always symmetrically, is there a way to get a asymmetric distribution of color values?

Here a minimal example of a plot using geom_tile():

data <- read.csv("http://protzkeule.de/data.csv")
p <- ggplot(data = data, aes(x = variable, y = meas)) + geom_tile(aes(fill = value))

plot with symmetrical limits:

p + scale_fill_gradient2(low = "blue", mid = "white", high = "red", guide = "colorbar",
                         limits = c(-0.1, 0.1))

but when changing the upper limit, the lower colormapping changes as well (watch the colorbar):

p + scale_fill_gradient2(low = "blue", mid = "white", high = "red", guide = "colorbar",
                         limits = c(-0.1, 0.3))
Henrik
  • 65,555
  • 14
  • 143
  • 159
Dahaniel
  • 383
  • 3
  • 8
  • I could be misunderstanding what you're looking for, but try passing `midpoint = -0.1` to `scale_fill_gradient2`. Is that what you want? – joran Jul 02 '12 at 21:22
  • I meant `0.1`, not `-0.1` there obviously, but I'm thinking now that isn't what you were looking for anyway, based on Brian's answer. – joran Jul 02 '12 at 21:36
  • why is the helpfile so poor for this functions? – Herman Toothrot Mar 29 '18 at 21:02

1 Answers1

34

What you want is scale_fill_gradientn. The arguments are not very clear (took me an hour or so to finally figure part of it out), though:

library("scales")
p + scale_fill_gradientn(colours = c("blue","white","red"), 
                         values = rescale(c(-.1,0,.3)),
                         guide = "colorbar", limits=c(-.1,.3))

Which gives:

enter image description here

Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
  • Thank you, I think now I got it. Correct me if I am wrong but with `values` you assign the values that a color from the `colours` vector is mapped to? The the only thing I don't get is what happens if the vector passed to `values` has more elements than the vector passed to `colours`. – Dahaniel Jul 03 '12 at 13:26
  • `values` and `colours` should have the same length. They are effectively paired, where the value corresponds to the color at that point, and everything between it and the next point is interpolated. I don't actually know what would happen if they were not the same length; it is at least conceptually an error, but I don't know if an actual error is thrown. In your example, -0.1 is mapped to blue, 0.0 is mapped to white, and 0.3 is mapped to red; values between -0.1 and 0.0 are interpolated between blue and white; values between 0.0 and 0.3 are interpolated between white and red. – Brian Diggs Jul 03 '12 at 16:38
  • @BrianDiggs I am using your solution in a similar way but is there a way to display the color bar discretely for the first handful of values? E.g. [the sepal length answer here](https://stackoverflow.com/questions/17713456/easiest-way-to-discretize-continuous-scales-for-ggplot2-color-scales) – guy Jun 22 '17 at 12:26
  • @tbone I don't know offhand. That would be worthy of its own question. – Brian Diggs Jun 28 '17 at 16:37
  • 3
    Update for anybody coming to this question after v 0.9, you'll have to do `library(scales)` to include the rescale command, as in https://stackoverflow.com/questions/10006317/ggplot2-quick-heatmap-plotting-reshape – elisa Jul 26 '17 at 10:15
  • Absolutely fabulous! I have struggled to find a solution to this problem and this answer was great, thank you ;) – umbe1987 Mar 10 '22 at 10:48