Search code examples
rggplot2colorsgeom-textcontinuous

Colour geom_text by a continue variable


I'm using geom_text to add text to a ggplot. I'd like the colour of that text to relate to the value it contains. This is a continuous scale, so ideally >0 get increasingly red, and <0 get increasingly green. However, the aes(colour = ...) argument in geom_text doesn't seem to like continuous variables.

Here's a simplified example

data <- structure(list(rpt = c(109.42, 109.9, 110.38, 110.86, 111.34, 
111.823333333333, 112.306666666667, 112.79, 113.273333333333, 
113.758333333333, 114.243333333333, 114.778333333333, 115.313333333333, 
115.8, 116.286666666667, 116.773333333333, 117.26, 117.591666666667, 
111.553333333333, 112.05, 112.546666666667, 113.001666666667, 
113.456666666667, 113.955, 114.453333333333, 114.953333333333, 
115.453333333333, 115.966666666667, 116.48, 116.963333333333, 
108.426666666667, 108.905, 109.383333333333, 109.88, 110.376666666667, 
110.856666666667, 111.336666666667, 111.82, 112.303333333333, 
112.773333333333, 113.243333333333, 113.743333333333, 114.243333333333, 
114.746666666667, 115.25, 115.753333333333, 116.256666666667, 
116.76, 117.263333333333, 117.75, 111.55, 112.018333333333, 112.486666666667, 
112.973333333333, 113.46, 113.976666666667, 114.493333333333, 
114.995, 115.496666666667, 115.968333333333, 116.44, 116.943333333333, 
117.446666666667, 117.666666666667), height.rel = c(0.189922480620155, 
0, 0.325581395348837, 0, 0.472868217054264, 0, 0.643410852713178, 
0, 0.872093023255814, 0, 1, 0, 0.794573643410853, 0, 0.468992248062016, 
0, 0.166666666666667, 0, 0.428571428571429, 0, 0.628571428571429, 
0, 0.79047619047619, 0, 0.952380952380952, 0, 1, 0, 0.714285714285714, 
0, 0.16044776119403, 0, 0.235074626865672, 0, 0.335820895522388, 
0, 0.492537313432836, 0, 0.727611940298508, 0, 0.932835820895522, 
0, 1, 0, 0.865671641791045, 0, 0.555970149253731, 0, 0.164179104477612, 
0, 0.380952380952381, 0, 0.578231292517007, 0, 0.836734693877551, 
0, 0.979591836734694, 0, 1, 0, 0.666666666666667, 0, 0.27891156462585, 
0), group = c("Unedited", "Unedited", "Unedited", "Unedited", 
"Unedited", "Unedited", "Unedited", "Unedited", "Unedited", "Unedited", 
"Unedited", "Unedited", "Unedited", "Unedited", "Unedited", "Unedited", 
"Unedited", "Unedited", "Partial_promoter", "Partial_promoter", 
"Partial_promoter", "Partial_promoter", "Partial_promoter", "Partial_promoter", 
"Partial_promoter", "Partial_promoter", "Partial_promoter", "Partial_promoter", 
"Partial_promoter", "Partial_promoter", "Unedited", "Unedited", 
"Unedited", "Unedited", "Unedited", "Unedited", "Unedited", "Unedited", 
"Unedited", "Unedited", "Unedited", "Unedited", "Unedited", "Unedited", 
"Unedited", "Unedited", "Unedited", "Unedited", "Unedited", "Unedited", 
"Partial_promoter", "Partial_promoter", "Partial_promoter", "Partial_promoter", 
"Partial_promoter", "Partial_promoter", "Partial_promoter", "Partial_promoter", 
"Partial_promoter", "Partial_promoter", "Partial_promoter", "Partial_promoter", 
"Partial_promoter", "Partial_promoter")), .internal.selfref = <pointer: 0x15c0262e0>, row.names = c(NA, 
-64L), class = c("data.table", "data.frame"))

caption <- structure(list(group = c("Partial_promoter", "Unedited"), ii.c = c(-3.93552369004191, 
-4.48565545498513)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-2L))

ggplot(data, 
       aes(x=rpt, y=height.rel, colour=group)) +
  geom_line() +
  facet_wrap(vars(group)) +
  geom_text(data = caption,
            aes(label = round(ii.c, 1)),
            x = 110, y = 1)

enter image description here

But when I try and add the colour to aes I get an error:

ggplot(data, 
       aes(x=rpt, y=height.rel, colour=group)) +
  geom_line() +
  facet_wrap(vars(group)) +
  geom_text(data = caption,
            aes(label = round(ii.c, 1),
                color = ii.c),
            x = 110, y = 1)

Error: Continuous value supplied to discrete scale

Any ideas? I'm stumped


Solution

  • That's nothing special about geom_text. In general in ggplot2 you have only one color scale and either is it continuous or discrete, i.e. you can't map a discrete and a continuous variable on the color aes at the same time.

    One option to overcome this limitation would be to use the ggnewscale package which allows to have multiple scales for the same aesthetic:

    library(ggplot2)
    
    ggplot(
      data,
      aes(x = rpt, y = height.rel, colour = group)
    ) +
      geom_line() +
      facet_wrap(vars(group)) +
      ggnewscale::new_scale_color() +
      geom_text(
        data = caption,
        aes(
          label = round(ii.c, 1),
          color = ii.c
        ),
        x = 110, y = 1
      )
    

    enter image description here