3
votes

I am trying to create a manual scale for the colors in one of my plots. My data span from 0 to 10, and I have quite a few very small numbers. Importantly I want two color gradients. One for points with values < 1, and one for points with values >= 1. Since I have quite a few very small numbers, I want to have the color gradient be on a log scale (diverging at 1).

Simulated data:

library(cowplot)
df <- data_frame(xs = rnorm(1000), 
                 ys = rnorm(1000),
                 color_vals =c(runif(500, 0,.001), runif(500, .01,10)))

I know I can do this automatically like so (I know it doesn't make sense to have a white point, but this is just a toy example for my more complex map plot):

ggplot(df, aes(x=xs, y=ys, color=color_vals)) + geom_point() +
       scale_color_gradient2(low="blue", high = "red", mid = "white", trans="log10")

enter image description here

I don't want this type of gradient though, because I want two increasing gradients, split at 1: (1) from grey to blue and (2) from yellow to red.

I know I can specify this with scale_color_gradientn this way:

ggplot(df, aes(x=xs, y=ys, color=color_vals)) + geom_point() +
       scale_color_gradientn(colors = c("grey", "blue", "yellow", "red"),
                             values = scales::rescale(c(0,1,1.000001, max(df$colors))))

enter image description here

but when I try to do this in tandem with the log transform, the gradient doesn't turn out correctly.

ggplot(df, aes(x=xs, y=ys, color=color_vals)) + geom_point() +
       scale_color_gradientn(trans = "log10",
                             colors = c("grey", "blue", "yellow", "red"),
                             values = scales::rescale(c(0.000001,1,1.000001, max(df$colors))))

enter image description here

The closest I've gotten is to attempt to log-transform the numbers within rescale, but that doesn't work properly (though it's close).

ggplot(df, aes(x=xs, y=ys, color=color_vals)) + geom_point() +
       scale_color_gradientn(trans = "log10",
                             colors = c("grey", "blue", "yellow", "red"),
                             values = scales::rescale(log10(c(0.000001,1,1.000001, max(df$colors)))))

enter image description here

So how can I specify the correct values for my two gradients if I also want to the gradients to be log transformed?

1
What is it that doesn't work properly about the last attempt? Is it the color bar itself or the colors shown (or both)?aosmith
It's the colors themselves. You can see that some values above 1 are still colored blue. Ideally the blue color would stop at 1, and anything above 1 would be on the yellow to red gradient. The first plot does this, but when I do it on the log scale, it no longer works.sjfox
How does it look if you use the smallest value in the dataset, min(df$colors) as your starting point for the log10 scaling instead of .000001?aosmith
Looks the same as the last plot above. I can't figure out why the log transformation makes setting the breakpoint values so difficultsjfox
What is color_vals ? You only create a colors variable in your data.frame. At the moment, I can not exactly reproduce your plots.bVa

1 Answers

2
votes

You're only specifying the limits for 2 colors, but you have 4 colors. It needs a start and end point for each color. Try the following. You can change the parameters depending on where you want your start/stop points:

 ggplot(df, aes(x = xs, y = ys, color = color_vals)) + 
 geom_point() +
 scale_color_gradientn(trans = "log10",
                    colors = c("grey", "blue", "yellow", "red"),
                    values = scales::rescale(log10(
                      c(0, 1, #grey parameters
                        1.000001, 2, #blue parameters
                        2.1, 3, #yellow parameters
                        3.1, max(df$color_vals))))) #red parameters

Since you mentioned you'd like to plot only 2 colors, you would delete the two middle value parameters, and delete two of the color options, as follows:

  ggplot(df, aes(x = xs, y=ys, color = color_vals)) + 
  geom_point() +
  scale_color_gradientn(trans = "log10",
                    colors = c("blue", "pink"),
                    values = scales::rescale(log10(
                      c(min(df$color_vals), 1,  # <1 (blue) parameters
                        1, max(df$color_vals))))) # >1 (pink) parameters