# Conditional or arbitrary fill in density plots?

I've tried googling this but can't find anything, so apologies if there's an obvious solution, but so far it's eluded me.

I ultimately want to create a `geom_density_ridges` plot using the `ggridges` package, and fill in the parts of the density plots where values are, for example, `>= -2 & =< 0` with some colour, and the part of the plot where `>=0.2 & <= 1` with another.

Below is the closest I've got whereby I create another `variable` which is conditional on the values of `x`. This sort of works for a histogram but obviously fails for `geom_density()` since ggplot treats each `fill` as a group. I basically just need to 'overlay' my arbitrary fills. Does that make sense?

``````library(tidyverse)

data <-
tibble(
x = rnorm(1000, mean = 0, sd = 1)
) %>%
mutate(
variable = case_when(
(x >= -2 & x <= 0) ~ "On",
(x >= 0.2 & x <= 1) ~ "Off",
TRUE ~ NA_character_
)
)

ggplot(data, aes(x, fill = variable)) +
geom_histogram(binwidth = 0.1, alpha = 0.7)
`````` ``````
ggplot(data, aes(x, fill = variable)) +
geom_density()
`````` Created on 2018-11-12 by the reprex package (v0.2.1)

This might be a good start for you - based on https://stackoverflow.com/questions/32722849/how-to-shade-specific-region-under-ggplot2-density-curve and https://stackoverflow.com/questions/48212824/shaded-area-under-density-curve-in-ggplot2

``````library(tidyverse)
z <-  rnorm(1000, mean = 0, sd = 1)

dens <- density(z)

data <- tibble(x = dens\$x, y = dens\$y) %>%
mutate(variable = case_when(
(x >= -2 & x <= 0) ~ "On",
(x >= 0.2 & x <= 1) ~ "Off",
TRUE ~ NA_character_))
#> Warning: package 'bindrcpp' was built under R version 3.4.4

ggplot(data, aes(x, y)) + geom_line() +
geom_area(data = filter(data, variable == 'On'), fill = 'grey') +
geom_area(data = filter(data, variable == 'Off'), fill = 'light blue')
`````` Created on 2018-11-12 by the reprex package (v0.2.1)

3 Likes

Thanks @jrlewi, this does exactly what I described. Since your solution finds the density estimates outside of `ggplot2`, I had to have a play about because I have another factor which I use in `facet_grid()` (my fault for not mentioning it earlier ). Combined with what you wrote, I managed to find a solution, although not at all elegant:

``````library(tidyverse)

data <- data.frame(
x = c(rnorm(1000, mean = 1, sd = 1), rnorm(1000, mean = 0, sd = 1), rnorm(1000,mean = -1, sd = 0)),
group = c(rep('a', 1000), rep('b', 1000), rep('c', 1000))
)

# Get density information for each group
densities <- data %>%
group_by(group) %>%
do(., dens = density(.\$x))

# Bind these into a data frame in order to plot them using ggplot2
densities_df <-
data.frame(
group = c(rep('a', 512),
rep('b', 512),
rep('c', 512)),
x = c(densities\$dens[]\$x,
densities\$dens[]\$x,
densities\$dens[]\$x),
y = c(densities\$dens[]\$y,
densities\$dens[]\$y,
densities\$dens[]\$y)
) %>%
mutate(
group = factor(group),
variable = case_when(
(x >= -2 & x <= 0) ~ "On",
(x >= 0.2 & x <= 1) ~ "Off",
TRUE ~ NA_character_
)
)

# Plot data
ggplot(densities_df, aes(x = x, y = y)) +
geom_area(data = filter(densities_df, variable == 'On'), fill = '#8ad5ae') +
geom_area(data = filter(densities_df, variable == 'Off'), fill = '#f8d0d2') +
geom_line(size = 1) +
facet_grid(.~group)
`````` Created on 2018-11-13 by the reprex package (v0.2.1)

Now I need to figure out how to crowbar this into `ggridges`... think I'll grab some lunch first.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.