2

The code below fills each of the two densities with color under the area of the curve:

library(ggplot2)

#fake data
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 2, 0.5))
                   , group = rep(c("C", "P"), each = 100))

#fill the area under the curve
ggplot(dat, aes(x = dens, fill = group)) + geom_density(alpha = 0.75)

How can I achieve the following two goals?

1) Only fill each curve within a specified interval. For example, interval [-1.5, 2.0] for group 'C' and [0.5, 2.8] for group 'P'.

2) Add a vertical segment (from x-axis to the curve) for each density. For example, at x=0.2 for group 'C' and at x=1.9 for group 'P'.

bluepole
  • 323
  • 1
  • 12
  • 1
    Lots of different answers at the linked questions. You can use some clever grouping, or (perhaps easier in this case) calculate the densities yourself beforehand. Let me know if you get stuck. – Axeman Jan 27 '20 at 17:55
  • @Axeman Thanks! Those links do help. However, there are two densities involved in the same plot in my case. How to deal with that? – bluepole Jan 27 '20 at 18:18

1 Answers1

4

To get you stared, here's your first question:

library(dplyr)
library(purrr)
library(tidyr)
library(ggplot2)

as.data.frame.density <- function(x) data.frame(x = x$x, y = x$y)

densities <- dat %>% 
  group_nest(group) %>% 
  mutate(dens = map(data, ~as.data.frame(density(.$dens)))) %>% 
  unnest(dens)

ggplot(densities, aes(x = x, y = y, group = group)) + 
  geom_density(stat = 'identity') +
  geom_density(
    aes(fill = group),
    . %>% filter((group == "C" & between(x, -1.5, 2.0)) | (group == "P" & between(x, 0.5, 2.8))),
    stat = 'identity',
    alpha = 0.75
  )

enter image description here

There are other ways of calculating the densities per group, using dplyr is just one way. It is probably good to set an equal bandwidth to the two density estimations.

Adding the segments is similar to this approach, you just need to find the correct values in the densities data.frame.

Axeman
  • 32,068
  • 8
  • 81
  • 94
  • Thanks for the solution! Is the `map()` function from the package `purrr`? Also, I got the following error: `Error in as.data.frame.default(density(.$dens)) : cannot coerce class ‘"density"’ to a data.frame` – bluepole Jan 27 '20 at 21:22
  • 1
    Just one more small correction: `library(tidyr)`. Thanks a lot! – bluepole Jan 27 '20 at 21:51