Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to shade a region under a curve using ggplot2

Tags:

I've been trying to use ggplot2 to produce a plot similar to this R graphic:

xv<-seq(0,4,0.01) yv<-dnorm(xv,2,0.5)  plot(xv,yv,type="l")  polygon(c(xv[xv<=1.5],1.5),c(yv[xv<=1.5],yv[xv==0]),col="grey")  

This is as far as I've gotten with ggplot2:

x<-seq(0.0,0.1699,0.0001)    ytop<-dnorm(0.12,0.08,0.02) MyDF<-data.frame(x=x,y=dnorm(x,0.08,0.02)) p<-qplot(x=MyDF$x,y=MyDF$y,geom="line")  p+geom_segment(aes(x=0.12,y=0,xend=0.12,yend=ytop)) 

I would like to shade the tail region beyond x=0.12. How would I do this using ggplot or qplot?

Broadly, how does one shade any subset under the curve, whether a tail, or between two arbitrary lines dividing the region into distinct areas?

Thanks for any advice.

like image 880
Tim Erickson Avatar asked Sep 14 '12 17:09

Tim Erickson


People also ask

How do I shade an area under a graph in R?

Method 1: Shade a graph using polygon function : In this method, we are calling the polygon function with its argument col passed with the name or the hex code of the color needed to be shaded in the given graph.

Does Ggplot only work with data frames?

ggplot only works with data frames, so we need to convert this matrix into data frame form, with one measurement in each row. We can convert to this “long” form with the melt function in the library reshape2 . Notice how ggplot is able to use either numerical or categorical (factor) data as x and y coordinates.


2 Answers

Create a polygon with the area you want to shade

#First subst the data and add the coordinates to make it shade to y = 0 shade <- rbind(c(0.12,0), subset(MyDF, x > 0.12), c(MyDF[nrow(MyDF), "X"], 0))  #Then use this new data.frame with geom_polygon  p + geom_segment(aes(x=0.12,y=0,xend=0.12,yend=ytop)) +      geom_polygon(data = shade, aes(x, y)) 

enter image description here

like image 81
Luciano Selzer Avatar answered Oct 13 '22 16:10

Luciano Selzer


This is essentially a copy of Luciano's answer which I found useful, however it may save some time for others wanting to use this approach.

Create the data. Here the density at 0.001 intervals from the 0.1th percentile to the 99.9th percentile of a normal distribution with specified mean and sd.

mean_ = 10 sd_ = 4  x = seq(qnorm(c(0.001), mean_, sd_),qnorm(c(0.999), mean_, sd_),0.001)   distdata = data.frame(x=x,y=dnorm(x,mean_,sd_)) 

A function for shading left or right tails from specific values.

shade_under_curve = function(p, d, left=NULL, right=NULL, distrib, fill, ...){    if(!is.null(left)){      shade = rbind(c(d[1, "x"], 0), d[d$x<left,], c(left,0))    } else if(!is.null(right)){      shade = rbind(c(right,0), d[d$x>right,], c(d[nrow(d), "x"], 0))    }    value = c(left, right)    ytop<-distrib(value,...)    p + geom_segment(aes(x=value,y=0,xend=value,yend=ytop)) +     geom_polygon(data = shade, aes(x, y), alpha=0.2, fill=fill)    } 

Examples:

p = qplot(x=distdata$x,y=distdata$y,geom="line")   shade_under_curve(p, distdata, left=3, distrib=dnorm, mean=mean_, sd=sd_, fill = "red")   shade_under_curve(p, distdata, right=15, distrib=dnorm, mean=mean_, sd=sd_, fill = "blue")  p2 = shade_under_curve(p, distdata, left=qnorm(0.025, mean_, sd_), distrib=dnorm, mean=mean_, sd=sd_, fill = "green")  shade_under_curve(p2, distdata, right=qnorm(0.975, mean_, sd_), distrib=dnorm, mean=mean_, sd=sd_, fill = "green")  
like image 30
Adam Waring Avatar answered Oct 13 '22 17:10

Adam Waring