I am trying to define the colours of groups of points plotted in ggplot. I adapted code from this post:
Color ggplot points based on defined color codes
but as soon as I have more than one row defined by the same grouping variable (rather than a separate colour for each row), the code fails, and I can't figure out why. Below is a reproducible example:
#create some data
zone <- c("E","E","C","C","C","E","E") #grouping variable
col <- c(50,100,150,200,250,300,350) #x variable
D <- c(.4,.45,.20,.22,.30,.31,.35) #y variable
df1 <- data.frame(zone, D, col); df1
#create a colour scheme based on grouping variable 'zone'
zone <-c("E","C")
color.codes<-as.character(c("#3399FF", "#FF0000"))
color.names<-c("blue", "red")
df2=data.frame(zone, color.codes, color.names); df2
# merge color specifications with data
df <-merge(df1,df2, by=("zone"), all.x=TRUE, all.y=TRUE); df
The data then look like this:
zone D col color.codes color.names
C 0.20 150 #FF0000 red
C 0.22 200 #FF0000 red
C 0.30 250 #FF0000 red
E 0.40 50 #3399FF blue
E 0.45 100 #3399FF blue
E 0.31 300 #3399FF blue
E 0.35 350 #3399FF blue
The goal is to produce a plot where points in zone 'C' are red and those in 'E' are blue, but using the code from the example cited everything is plotted in red:
p <- ggplot(data=df, aes(col, D, colour = zone))+
geom_point()
p + scale_colour_manual(breaks = df$zone, values = df$color.codes)
Can anyone see the fatal flaw, why this code won't work across groups in this way?
Thanks so much in advance
You are somewhere between two different solutions.
One approach is to not put the colors into the
df
data frame and specify the mapping betweenzone
and desired color in the scale call:Note that this does not use
color.codes
orcolor.names
fromdf
, nor does it usedf2
directly (though it does use the columns that are used to makedf2
; if you have something likedf2
and not the columns separately, you can usesetNames(df2$color.codes, df2$zone)
instead).The other approach maps color directly to the color codes and uses
scale_color_identity
, but then has to go through some additional labeling to get the legend right.The first is, in my opinion, the better solution.
It works if you use
unique
andas.character
:Sven beat me by a few secs, but slightly different: