I am trying to create a line plot and have one of the groups use a dotted line type. Unfortunately the whiskers can be hard to see with dotted lines so I am trying to add solid lines for the whiskers.
I tried to follow the suggested solution in this questions.
ggplot2 geom_errorbar with different linetype but with solid whiskers
Unfortunately something weird is happening when also using position dodge.
library(ggplot2)
library(dplyr)
dat <- data.frame(cohort = rep(c("Placebo", "Trt 1", "Trt 2"), times = 3),
visit = c(rep("Baseline", times = 3), rep("Time 2", times = 3), rep("Time 3", times = 3)),
visitnum = c(rep(1, times = 3), rep(2, times = 3), rep(3, times = 3)),
mean = rnorm(9)
) %>%
mutate(lower = mean - 1,
upper = mean + 1)
dodge <- position_dodge2(.25)
dat %>% ggplot(aes(x = visitnum, y = mean, color = cohort, group = cohort, linetype = cohort)) +
geom_line(position = dodge) +
geom_point(position = dodge) +
geom_linerange(aes(ymin = lower, ymax = upper),
position = dodge) +
geom_segment(aes(x = visitnum-.1, xend = visitnum+.1, y = lower, yend = lower), position = dodge, linetype = "solid") +
geom_segment(aes(x = visitnum-.1, xend = visitnum+.1, y = upper, yend = upper), position = dodge, linetype = "solid") +
scale_linetype_manual(values = c("solid", "solid", "dotted")) +
scale_x_continuous(breaks = unique(dat$visitnum), labels = unique(dat$visit))
The lines created by geom_segment seem to be right adjusted.
Any help would be greatly appreciated.
One option would be to "manually" dodge the whiskers aka segments by computing the x
and xend
positions yourself instead of relying on position_dodge
:
library(ggplot2)
set.seed(123)
dw <- .45
dodge <- position_dodge(dw)
dat$cohort_num <- as.numeric(factor(dat$cohort))
dat |> ggplot(aes(x = visitnum, y = mean, color = cohort, group = cohort, linetype = cohort)) +
geom_line(position = dodge) +
geom_point(position = dodge) +
geom_linerange(aes(ymin = lower, ymax = upper),
position = dodge
) +
geom_segment(
aes(
x = visitnum - .05 + dw / 3 * scales::rescale(cohort_num, to = c(-1, 1)),
xend = visitnum + .05 + dw / 3 * scales::rescale(cohort_num, to = c(-1, 1)),
y = lower, yend = lower
),
linetype = "solid"
) +
geom_segment(
aes(
x = visitnum - .05 + dw / 3 * scales::rescale(cohort_num, to = c(-1, 1)),
xend = visitnum + .05 + dw / 3 * scales::rescale(cohort_num, to = c(-1, 1)),
y = upper, yend = upper
),
linetype = "solid"
) +
scale_linetype_manual(values = c("solid", "solid", "dotted")) +
scale_x_continuous(breaks = unique(dat$visitnum), labels = unique(dat$visit))