Control middle value colours with scale_colour_con

2019-07-04 10:56发布

问题:

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?

回答1:

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")


回答2:

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.



标签: r colors ggplot2