For anyone interested, I settled on using geom_segment and clip = "off" in coord_cartesian(). I'm sure there's a way to generalize this so its not so manual. It is a little finicky to plot size...
library(tidyverse)
set1 = tribble(
~phase, ~session, ~outcome,
"baseline", 1, 0,
"baseline", 2, 10,
"baseline", 3, 10,
"baseline", 4, 0,
"baseline", 5, 0,
"treatment", 6, 20,
"treatment", 7, 30,
"treatment", 8, 40,
"treatment", 9, 40,
"treatment", 10, 50,
"treatment", 11, 60,
"treatment", 12, 80,
"treatment", 13, 90,
"treatment", 15, 90,
"treatment", 17, 80,
"treatment", 19, 100,
"treatment", 21, 90
) %>% mutate(set = "set1")
set2 = tribble(
~phase, ~session, ~outcome,
"baseline", 1, 10,
"baseline", 2, 10,
"baseline", 3, 10,
"baseline", 4, 5,
"baseline", 5, 0,
"baseline", 6, 10,
"baseline", 7, 10,
"baseline", 8, 10,
"baseline", 9, 5,
"baseline", 10, 0,
"baseline", 11, 10,
"baseline", 12, 10,
"baseline", 13, 10,
"treatment", 14, 20,
"treatment", 15, 30,
"treatment", 16, 40,
"treatment", 17, 50,
"treatment", 18, 50,
"treatment", 19, 70,
"treatment", 20, 80,
"treatment", 21, 90
) %>% mutate(set = "set2")
dat = bind_rows(set1, set2)
lines = tibble(
set = c("set1","set2"),
line = c(5.5, 13.5)
)
dat %>%
ggplot(aes(x = session, y = outcome, group = phase)) +
geom_line() +
geom_point() +
geom_segment(data = lines, inherit.aes = F, aes(x = line, xend = line, y = 0, yend = 100)) +
lemon::facet_rep_grid(set~., repeat.tick.labels = T) +
scale_x_continuous(minor_breaks = seq(1, 25, 1), breaks = c(1, 5, 10, 15, 20, 25)) +
theme_bw(base_size = 14) +
coord_cartesian( ylim = c(0, 100), clip = 'off') +
geom_segment(data = tibble(set = "set1", x = 5.5, xend = 13.5),
inherit.aes = F,
aes(x = x, y = 0, xend = xend, yend = 0)) +
geom_segment(data = tibble(set = "set1", x = 13.5, xend = 13.5),
inherit.aes = F,
aes(x = x, y = 0, xend = xend, yend = -15)) +
geom_segment(data = tibble(set = "set2", x = 13.5, xend = 13.5),
inherit.aes = F,
aes(x = x, y = 100, xend = xend, yend = 115))

Created on 2022-04-06 by the reprex package (v2.0.1)