Geom_Ribbons : Change color of fill according to position of threshold

1,067 views
Skip to first unread message

Benjamin Mewes

unread,
Nov 3, 2015, 7:39:48 AM11/3/15
to ggplot2
Hi all,

I want to color the fill of a ribbon differently according to its location above a threshold value:

x <- seq(1:10)
y <- c(1000,2000,3000,2000,5000,6000,1500,8000,500,10000)

df <- data.frame(x,y)

h <- ggplot(df, aes(x=x, y=y))

h + geom_line()+geom_ribbon(aes(ymin=mean(y),ymax=y),fill="Red") + geom_ribbon(aes(ymin=y,ymax=min(y),fill="Blue")


Every area under mean(y) should be blue, everything above red. But ggplot2 renders the plot always in one color only. Any idea?

Crump, Ron

unread,
Nov 3, 2015, 11:42:01 AM11/3/15
to Benjamin Mewes, ggplot2
Hi Benjamin,
The code you supplied didn¹t run without adding another bracket, but then
you might be overwriting layers. Here¹s what I¹ve gotŠ

#
# I believe you want a line between your data points. Where this line is >
mean(y),
# you want the area between the line and mean(y) to be red, where it is
below mean(y)
# you want the area between the line and mean(y) to be blue.
#
# If I'm right I think you need two ribbons which won¹t overlap:
# one with minimum value mean(y) and maximum value pmax(y,mean(y)), and
# one with maximum value mean(y) and minimum values pmin(y,mean(y))
#
# However, to keep the ribbons in agreement with the line, I think you
need extra data
# points where the line crosses the mean(y) horizontal, which we'll
linearly interpolate.
#
x <- seq(1:10)
y <- c(1000,2000,3000,2000,5000,6000,1500,8000,500,10000)
df <- data.frame(x,y)
# Find where y > mean(y)
flip <- df$y > mean(df$y)
# find x values after a line will cross mean(y)
cpos <- which( flip[1:(length(flip)-1)] != flip[2:length(flip)] )
# linear interpolation to get x values at which y == mean(y)
df2<-rbind(df, # Original data

data.frame(x=df$x[cpos]+(df$x[cpos+1]-df$x[cpos])*((df$y[cpos]-mean(df$y))/
(df$y[cpos]-df$y[cpos+1])),y=mean(y)))
# re-order
df2 <- df2[order(df2$x,decreasing=FALSE),]

h <- ggplot(df2)+
geom_ribbon(aes(x=x,ymin=mean(y),ymax=pmax(y,mean(y))),fill="red")+
geom_ribbon(aes(x=x,ymin=pmin(y,mean(y)),ymax=mean(y)),fill="blue")+
geom_line(aes(x=x,y=y))


Benjamin Mewes

unread,
Nov 4, 2015, 2:03:04 AM11/4/15
to ggplot2, bennam...@gmail.com, R.E....@warwick.ac.uk
Thank's a lot :)

Really neat way with that flip!
Reply all
Reply to author
Forward
0 new messages