I have a set of data and would like to map the colour
aesthetic around a sort of "reference value" like so:
- values below are red
- values near are blue
- values above are green
I still want to show the fact that values are on a continuoum, so simply using a function like cut()
and using scale_colour_discrete
is not what I'm looking for. Here's some example data:
set.seed(123)
x <- runif(100, min = 1, max = 10)
y <- runif(100, min = 1, max = 10)
test <- data.frame(x = x, y = y)
test$colour <- runif(100, min = 1, max = 10)
ggplot(test, aes(x = x, y = y, colour = colour)) + geom_point(size = 3)
That produces the following:
I'm familiar with scale_colour_gradient(low = "red", high = "green")
, however I was hoping to more deliberately transition my colours along desired value mapping to make the regions "pop" a bit more visually. Spacing would not necessarily be linear. in other words, for a reference value of 3, the mapping would be something like this:
value: 1 3 10
colour: red blue green
Is this possible? I'd also take alternative solutions to accomplish a good visualization to highlight "desirable" values easily among a sea of points. For example, I considered replacing values near the reference such that (ref - tol < colour < ref + tol) <- NA
, and then using scale_colour_gradient
's option for na.value
.
Or should I truly be considering the cut()
option, just with a very small cut size and then figure out how to gradually change the colours along the resultant breaks?
From http://docs.ggplot2.org/0.9.2.1/scale_gradient2.html:
scale_color_gradient2(low = "red", midpoint = 3, mid = "blue", high = "green")
UPDATE:
Concerning OP's comment - playing around with midpoints and space="Lab"
helps:
# Using the Lab colour space also improves perceptual properties
# at the price of slightly slower operation
d + scale_colour_gradient2(space="Lab")
Back from the graveyard - given the newest comment I realized that one should put the two lines of code together:
scale_color_gradient2(low = "red",
midpoint = 3,
mid = "blue",
high = "green",
space="Lab")
It is possible to define three or more colours and to specify how the data values map to the colour scale with scale_colour_gradientn()
. You want to define your colours and use the values=
option to define the mapping from data to colour.
The following would implement the three-colour scheme that you suggest:
set.seed(123)
x <- runif(100, min = 1, max = 10)
y <- runif(100, min = 1, max = 10)
test <- data.frame(x = x, y = y)
test$colour <- runif(100, min = 1, max = 10)
test.plot <- ggplot(test, aes(x = x, y = y, colour = colour)) +
geom_point(size = 3) +
scale_colour_gradientn(colours=c("red","blue","green"),
values=rescale(c(1,3,10)),
space = "Lab")
test.plot
This produces a graph as illustrated here (sorry; I don't have the reputation points to embed the image).
Regarding the second part of your question, to highlight specific values, one option is to re-plot in a different colour. Going back to your original plot with the dark- to light-blue colour gradient, we can replot points near a colour value of 3 in red. To avoid any visual artifacts from the overlaid points, we can use differently-sized points, either by specifying size =
or by using a larger shape via shape =
(as is done in the qcc package).
test2 <- test[test$colour > 2.5 & test$colour < 3.5,]
test2.plot <- ggplot(test, aes(x = x, y = y, colour = colour)) +
geom_point(size = 3, shape = 20) +
geom_point(data = test2, aes(x = x, y = y),
colour = "red", size = 3, shape = 19)
test2.plot
Here's the sample graph.
Since this overplotting doesn't show up on the legend, some additional work would be needed to label the highlighted points.