I have data that I'd like to ggplot
with a gradient coloring scheme and then annotate some of the points.
My data:
df <- data.frame(id = rep(LETTERS,100),
val1 = rnorm(100*length(LETTERS)), val2 = rnorm(100*length(LETTERS)),
sig = runif(100*length(LETTERS),0,1),
col = NA,stringsAsFactors = F)
Here I select a few points I'd like to annotate and give them colors:
df$col[sample(nrow(df), 10, replace = F)] <- rainbow(10)
And here's the ggplot
code I'm trying:
library(ggplot2)
library(ggrepel)
ggplot(df,aes(x=val1,y=val2,color=col))+
geom_point(aes(color=sig),cex=2)+scale_colour_gradient2("Significance",low="darkred",mid="darkblue",high="darkred")+
geom_text_repel(data=dplyr::filter(df,!is.na(col)),aes(x=dplyr::filter(df,!is.na(col))$val1,y=dplyr::filter(df,!is.na(col))$val2,label=dplyr::filter(df,!is.na(col))$id,colour=dplyr::filter(df,!is.na(col))$col))+
theme_minimal()+theme(legend.position="none")
which throws this error:
Error: Discrete value supplied to continuous scale
Any idea?
Basically there are two approaches. One is to map the continuous variable to fill and the discrete text variable to color inside the aes call. And the other is to map the continuous variable to color inside aes and to map manually the text outside aes call.
1st approach - mapping continuous scale to fill, and using a shape(pch = 21
) that supports fill aesthetic. I used scale_fill_gradientn
and manually defined where the colors should lie in the data range - values = scales::rescale(c(min(df$sig), median(df$sig), max(df$sig)))
.
After that it is easy to map the discrete scale (repel labels) to the color aesthetic. However one needs to define the order of the levels to match the colors supplied in scale_colour_manual
library(tidyverse)
ggplot(df,aes(x = val1, y = val2))+
geom_point(aes(fill = sig), cex=2, pch = 21)+
scale_fill_gradientn("Significance",colors = c("darkred", "darkblue","darkred"), values = scales::rescale(c(min(df$sig), median(df$sig), max(df$sig))))+
geom_text_repel(data = dplyr::filter(df,!is.na(col)) %>%
mutate(col = factor(col, levels = col)),
aes(x = val1, y = val2, label = id, color = col), size = 6)+
scale_colour_manual(values = dplyr::filter(df,!is.na(col))[,5])+
theme_minimal()+
theme(legend.position = "none")
2nd approach - specify color for geom_text_repel outside the aes call.
ggplot(df,aes(x = val1, y = val2)) +
geom_point(aes(color= sig), cex=2) + scale_colour_gradient2("Significance",low="darkred",mid="darkblue",high="darkred")+
geom_text_repel(data = dplyr::filter(df,!is.na(col)), aes(x = val1, y = val2, label = id), color = dplyr::filter(df,!is.na(col))[,5], size = 6)+
theme_minimal()+
theme(legend.position = "none")