Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2: Bring one line to the front, but save the colors

Tags:

r

layer

ggplot2

Consider the following code:

library(ggplot2)
foo <- data.frame(x=1:10,A=1:10,B=10:1)
ggplot(melt(foo,id.vars="x"),aes(x,value,color=variable))+geom_line(size=5)

enter image description here

I want to bring the red line (A) to the front, on top of B (see the cross point), while the colors and the order they appear in the legend do not change. Is there any way?

like image 537
Ali Avatar asked Jan 14 '14 17:01

Ali


3 Answers

Try this,

last_plot() + aes(group=rev(variable))
like image 78
baptiste Avatar answered Sep 25 '22 12:09

baptiste


Replotting the red line using a subsetted dataframe does the trick.

library(ggplot2)
foo <- data.frame(x=1:10,A=1:10,B=10:1)
require(reshape2)
fooM <- melt(foo,id.vars="x")
p<-ggplot()
p<-p+geom_line(data=fooM[fooM$variable!="A",],aes(x,value,color=variable),size=5)
p<-p+geom_line(data=fooM[fooM$variable=="A",],aes(x,value,color=variable),size=5)
p

EDIT: Note that ggplot applies layers sequentially on top of each other - this can be best leveraged when constructing the plot line by line.

EDIT2: @tonytonov is right that one may want to avoid plotting identical things twice. Modified my answer to plot everything but A the first time, then only A. Result remains the same and is now also compatible with transparency or big data ;)

like image 5
CMichael Avatar answered Sep 27 '22 12:09

CMichael


The solution with replotting is fine unless you have reasons to avoid it. I can think of at least two: using alpha (transparency) or performance issues (you need to do it in one run, big data).

Here's what I propose:

require(scales)
# give the desired order here, I just use reverse
# separate function since we apply it over both levels & colors
shuffle <- function(x) rev(x)
foo <- data.frame(x=1:10, A=1:10, B=10:1, C=2.5, D=7.5)
melt_foo <- melt(foo, id.vars="x") 
# original plot
ggplot(melt_foo, aes(x, value, color=variable)) + 
  geom_line(size=5)

enter image description here

orig_order <- levels(melt_foo$variable)
new_order <- shuffle(orig_order)
# grabbing default colours
orig_colors <- hue_pal()(length(new_order))
new_colors <- shuffle(orig_colors)
melt_foo$variable <- factor(melt_foo$variable, levels=new_order)
# levels _and_ colours reversed, legend appearance stays the same
ggplot(melt_foo, aes(x, value, color=variable)) + 
  geom_line(size=5) + 
  scale_colour_manual(values=new_colors, labels=orig_order, breaks=orig_order) 

enter image description here

like image 4
tonytonov Avatar answered Sep 25 '22 12:09

tonytonov