1

I am attempting to create a plot that shades the area under the curve of a density plot between two points. Here's what I have so far:

df.ind <- data.frame(x=rnorm(1000))
df.group <- data.frame(group = factor(1:20))
df.group$gr.mean <- rnorm(20)
df.group$width <- 1 + abs(rnorm(20))
df.group$upper <- df.group$gr.mean + df.group$width
df.group$lower <- df.group$gr.mean - df.group$width

I can then create a ggplot where I use the density of x from df.ind and plot it 20 different times (by each group). I then overlay the vertical lines. What I want to do is shade the area between the lines.

ggplot(df.group) + 
  stat_density(data=df.ind, mapping=aes(x), 
               geom="line", position="dodge") +
  facet_wrap(~group) + 
  geom_vline(aes(xintercept=lower)) +
  geom_vline(aes(xintercept=upper))

I'm aware of a similar question here: ggplot2 shade area under density curve by group and here: Shading a kernel density plot between two points.

But my data come from two different data.frame objects. Therefore, I can't use the clever trick they use to aggregate the data...

Community
  • 1
  • 1
Alex
  • 1,997
  • 1
  • 15
  • 32
  • Well, merge your data frames and use the previously suggested methods. – MrFlick May 04 '15 at 21:10
  • @MrFlick - there's nothing to merge on, though. They don't share any common characteristics. – Alex May 04 '15 at 21:11
  • 2
    Well then you'll need to repeat the individual data for each group. Or you could pre-calculate the density curve once and repeat that data for each group. ggplot isn't going to do any special polygon overlap detection. you need to calculate the data you want to plot. – MrFlick May 04 '15 at 21:14
  • Thanks. That works. Don't know why that didn't occur to me before. – Alex May 04 '15 at 21:35

1 Answers1

3

Like I mentioned in the comments, you are going to have to do the work of creating data specifically for each panel yourself. Here's one way

# calculate density
dx<-density(df.ind$x)

#define areas for each group
mm <- do.call(rbind, Map(function(g, l,u) {
    data.frame(group=g, x=dx$x, y=dx$y, below=dx$x<l, above= dx$x > u)
}, df.group$group, df.group$lower, df.group$upper))

#plot data
p2<-ggplot(mm) + 
   geom_area(aes(x, y, fill=interaction(below,above))) + 
   geom_vline(data=df.group, aes(xintercept=lower)) +
   geom_vline(data=df.group, aes(xintercept=upper)) +
   facet_wrap(~group)

enter image description here

MrFlick
  • 195,160
  • 17
  • 277
  • 295