Adding summary information to a density plot created with ggplot

12,291

Solution 1

You can use the geom_area() function. First make the density explicit using the density() function.

x <- as.vector(rnorm(10000))
d <- as.data.frame(x=x)
library(ggplot2)
p <- ggplot(data = d) + theme_bw() + 
  geom_density(aes(x=x, y = ..density..), color = 'black')
# new code is below
q5 <- quantile(x,.05)
q95 <- quantile(x,.95)
medx <- median(x)
x.dens <- density(x)
df.dens <- data.frame(x = x.dens$x, y = x.dens$y)
p + geom_area(data = subset(df.dens, x >= q5 & x <= q95), 
              aes(x=x,y=y), fill = 'blue') +
    geom_vline(xintercept = medx)

alt text

Solution 2

I wanted to add to @Prasad Chalasani's answer for those like myself that came looking to add all 3 Std areas. 1 Std is the darkest shade, 2 Std is the middle shade, and 3 Std is the lightest shade. The mean is the black line and the median is the white line.

set.seed(501) # Make random sample reproducible
x <- as.vector(rnorm(100))
d <- as.data.frame(x=x)
library(ggplot2)

p <- ggplot(data=d) +
     theme_bw() + 
     geom_density(aes(x=x, y = ..density..), color = '#619CFF')

# new code is below
q15.9 <- quantile(x, .159) # 1 Std 68.2%
q84.1 <- quantile(x, .841)
q2.3  <- quantile(x, .023) # 2 Std 95.4%
q97.7 <- quantile(x, .977)
q0.01 <- quantile(x, .001) # 3 Std 99.8%
q99.9 <- quantile(x, .999)
meanx <- mean(x)
medx  <- median(x)
x.dens  <- density(x)
df.dens <- data.frame(x=x.dens$x, y=x.dens$y)

p + geom_area(data = subset(df.dens, x >= q15.9 & x <= q84.1), # 1 Std 68.2%
              aes(x=x,y=y), fill='#619CFF', alpha=0.8) +
    geom_area(data = subset(df.dens, x >= q2.3 & x <= q97.7), # 2 Std 95.4%
              aes(x=x,y=y), fill='#619CFF', alpha=0.6) +
    geom_area(data = subset(df.dens, x >= q0.01 & x <= q99.9), # 3 Std 99.8%
              aes(x=x,y=y), fill='#619CFF', alpha=0.3) +
    geom_vline(xintercept=meanx) +
    geom_vline(xintercept=medx, color='#FFFFFF')

enter image description here

Solution 3

This (also) does the vertical line at the median:

ggplot(data = d) + theme_bw() + 
   geom_density(aes(x=x, y = ..density..), color = 'black') + 
   geom_line(aes(x=median(x), y=c(0,.4) ) )
Share:
12,291
David LeBauer
Author by

David LeBauer

I am a scientist interested in optimizing agricultural systems to maximize yield while reducing inputs and enhancing ecosystem services. Many of my questions on SO and related sites are related to the development of software, databases, and statistical analyses to support scientific research aimed at predicting ecosystem response to global change and engineering new systems for sustainable food and fuel production. Key projects include: TERRA REF An open access data and computing platform to support high throughput penotyping web github PEcAn (Predictive Ecosystem Analyzer), a model-data synthesis framework: code; project website; web interface BETYdb, A database of plant traits, crop yields, and computational provenance code; web interface BioCro: crop productivity and ecosystem services simulator: code Ecosystem Climate Regulation Services Calculator: code; demo

Updated on July 28, 2022

Comments

  • David LeBauer
    David LeBauer almost 2 years

    I have a density plot and I would like to add some summary information such as placing a line at the median and shading the 90% credible intervals (5th and 95th quantiles). Is there a way to do this in ggplot?

    This is the type of plot that I would like to summarize:

    I can figure out how to draw a line from the y=0 to y= density(median(x)), but it is not clear to me if I can shade the plot with a 90% CI. Alternatively, I could add a horizontal boxplot above the density plot, but it is not clear how to rotate the boxplot by itself, without rotating the density plot along with it.

    x <- as.vector(rnorm(10000))
    d <- as.data.frame(x=x)
    library(ggplot2)
    ggplot(data = d) + theme_bw() + 
      geom_density(aes(x=x, y = ..density..), color = 'black')
    

    alt text

  • David LeBauer
    David LeBauer over 13 years
    @pchalansani thanks for showing me this. that is exactly what I was hoping to do... now I just need to get the median line in there. I've been trying to use geom_vline but that doesn't seem to work.
  • Prasad Chalasani
    Prasad Chalasani over 13 years
    @David I updated it with the median line, not sure why geom_vline wasn't working for you
  • David LeBauer
    David LeBauer over 13 years
    @pchalansani thanks for helping me move forward with this. looks nice.
  • David LeBauer
    David LeBauer over 13 years
    @pchalansani thanks for the update, but I am having the trouble that geom_vline places the line at x=0 instead of at the median. If you transform x, x <- x+10, you will see the density moves but the line doesn't...
  • Prasad Chalasani
    Prasad Chalasani over 13 years
    @David I looked at the geom_vline help page, and it seems you need to use xintercept... that works, I fixed the code... had.co.nz/ggplot2/geom_vline.html
  • David LeBauer
    David LeBauer over 13 years
    @pchalansani thanks! I misread that and thought that it said 'intercept'