Ed G
Ed G

Reputation: 822

Make geom_text colour darker than geom_point colour

I am labeling a scatter plot with values. To make it readable, I want the text colour to be darker than the points (a green point would have a darker green label):

p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width, col = Species))+
  geom_point()+
  geom_text(aes(label = Sepal.Length), size = 2, position = position_dodge(width = 0.2))

I can use scale_colour_discrete to create the effect I want, but it applies to both points and text.

p1 + scale_colour_discrete(l = 50)

Can I apply it to the text only?

Upvotes: 4

Views: 1862

Answers (2)

Roman
Roman

Reputation: 17668

You can try:

# specify your colour
COL <- c("red", "blue", "green")
p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width, col = Species))+
      geom_point()
p1 <- p1 + scale_colour_manual(values = COL)

Now darken your colour using col2rgb and rgb (source) or another approach

COL2 <- col2rgb(COL)
COL2 <- COL2/2  # you can use of course other values than 2. Higher values the darker the output.
COL2 <- rgb(t(COL2), maxColorValue=255)

Plot the labels.

p1  + geom_text(aes(label = Sepal.Length), col=factor(iris$Species, labels=COL2), size = 2, position = position_dodge(width = 0.2))

For better overview I recommend to use geom_text_repel. Of note, you have to use as.character.

require(ggrepel)
p1 +   geom_text_repel(aes(label = Sepal.Length), size = 2, col= as.character(factor(iris$Species, labels=COL2)))

enter image description here

If you don't want to specify a colour in the beginning you can also extract the original ggplot colors using:

g <- ggplot_build(p1)
COL <- unlist(unique(g$data[[1]]["colour"]))

Then you use the code above for the darker text colour or combine everything in a darker function:

p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width, col = Species))+
      geom_point()
# function 
darken <- function(Plot, factor=1.4){
  g <- ggplot_build(Plot)
  color <- unlist((g$data[[1]]["colour"]))
  col <- col2rgb(color)
  col <- col/factor
  col <- rgb(t(col), maxColorValue=255)
  col
}

# basic text
p1  + geom_text(aes(label = Sepal.Length), col=darken(p1, 2), size = 2, position = position_dodge(width = 0.2))
# repel text
p1  + geom_text_repel(aes(label = Sepal.Length), col= darken(p1, 2), size = 2)

Upvotes: 1

Shirin Elsinghorst
Shirin Elsinghorst

Reputation: 310

Define colors for points:

n <- length(levels(iris$Species))
cols_points <- hcl(h = seq(15, 375, length = n + 1), l = 65, c = 100)[1:n]

Plot points as you did initially but set colors manually:

p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) + geom_point() + scale_colour_manual(values = cols_points)

Define text colors by taking the same colors as you used for the plots but changing the hue (l, can be adjusted to how dark you want it):

cols_text <- hcl(h = seq(15, 375, length = n + 1), l = 30, c = 100)[1:n]

iris_cols <- ifelse(iris$Species == "setosa", cols_text[1], 
                ifelse(iris$Species == "versicolor", cols_text[2], cols_text[3]))

Plot with text annotation (I added a small y-offset, so that text and points don't overlap):

p1 + annotate("text", x = iris$Sepal.Length, y = iris$Sepal.Width + 0.05, label = iris$Sepal.Length, color = iris_cols, size = 2)

Upvotes: 1

Related Questions