I have this sample density curve data (found here):
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_))
I plot this curve with ggplot2, along with highlighted regions using geom_area, along with some text created using geom_text outside the plot boundaries, requiring me to turn off clipping in coord_cartesian:
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') +
geom_text(aes(x = 7, y = 0.15, label = "test")) +
theme(plot.margin = unit(c(1,7,1,1), "lines")) +
coord_cartesian(xlim = c(-5, 5),
# ylim = c(0.1, 0.2),
clip = "off")

What I would like to do now, is to zoom into y-axis between 0.1 and 0.2. I know that if I use the limits argument in scale_y_continuous, then this can sometimes remove data which is constraining the view, so I use the ylim argument inside coord_cartesian set as c(0.1, 0.2).
However, this causes the density area and curve to overlap the plot boundaries (as I've turned off clipping).

What I could do now, is to turn on clipping in coord_cartesian, however this would now remove the geom_text outside the plot boundaries which I need. Is there any way to reconcile my issue?

This is a good use case to use the oob argument of the position scales in a non-standard way. The scales package has several out-of-bounds function that can serve you here, notably oob_squish(), which sets out-of-bounds to nearest limits, or oob_keep(), which keeps out-of-bounds data, similar to setting coordinate limits.
library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 4.0.2
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_))
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') +
geom_text(aes(x = 7, y = 0.15, label = "test")) +
theme(plot.margin = unit(c(1,7,1,1), "lines")) +
scale_y_continuous(limits = c(0.1, 0.2),
expand = c(0, 0),
oob = scales::oob_squish) +
scale_x_continuous(limits = c(-5, 5),
oob = scales::oob_keep) +
coord_cartesian(clip = "off")

Created on 2020-12-25 by the reprex package (v0.3.0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With