Reputation: 95
Long time lurker here.
I am plotting the predicted values from a previously run, nlme model using the output by ggpredict. I have built a line plot and want to create error bars on the points. Though, reviewers want the error bars to only be going one direction (i.e., for the group who is higher = positive error bars, while the group who is negative gets negative error bars). I've successfully done this with this code:
Q1 <- ggpredict(MODEL, c("day", "group"),
#ci.lvl = NA,
type = "re")
q2 <- Q1 %>%
mutate(is.int = group == "Intervention",
conf.high = ifelse(is.int, std.error, conf.high),
conf.low = ifelse(is.int, 0, conf.low)) %>%
select(-is.int) %>%
mutate(is.cntr = group == "Control",
conf.high = ifelse(is.cntr, 0, conf.high),
conf.low = ifelse(is.cntr, std.error, conf.low)) %>%
select(-is.cntr)
ggplot(data = q2,
aes(x, predicted, group = group)) +
geom_point(aes(shape = group), size = 6) +
scale_shape_manual(values=c(19, 1)) +
geom_line(size = 2,
aes(linetype = group),
color = "black") +
scale_linetype_manual(values = c("solid", "dashed")) +
geom_linerange(size = 1,
aes(ymin = predicted - conf.low,
ymax = predicted + conf.high),
color = "black",
alpha = .8) +
labs(x = "Time",
y = "",
linetype = "",
shape = "")
scale_y_continuous(limits =c(1500, 2000)) +
geom_bracket(
xmin = "PRE", xmax = c("MID1", "MID2", "MID3", "POST"),
y.position = c(1850,1900,1950,2000), tip.length = 0.05,
label = c("*", "**", "***", "#"), size = 1)
and it works well.
however
The reviewers would like "caps" on the end of the error bars that i've reated with geom_linerange()
. Obviously, geom_errorbar()
is almost purpose built to have the "caps". But, when I use it, it creates lines across my data. See pic attached for example.
Thoughts??
Edit, Reproducibile data:
dput(q2)
structure(list(x = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L,
5L, 5L), .Label = c("PRE", "MID1", "MID2", "MID3", "POST"), class = "factor"),
predicted = c(1666.97185871754, 1660.27445165342, 1743.2831065274,
1678.48945165342, 1788.50605542978, 1637.40907049806, 1807.55826371403,
1639.78265640012, 1865.8766220711, 1652.91070173056), std.error = c(88.8033117577884,
91.257045996107, 92.9973963841595, 95.3834973421298, 95.0283457128716,
97.3739053806999, 95.6466346849776, 97.9142418717957, 93.3512943191676,
95.5735155125126), conf.low = c(0, 91.257045996107, 0, 95.3834973421298,
0, 97.3739053806999, 0, 97.9142418717957, 0, 95.5735155125126
), conf.high = c(88.8033117577884, 0, 92.9973963841595, 0,
95.0283457128716, 0, 95.6466346849776, 0, 93.3512943191676,
0), group = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L,
2L), .Label = c("Intervention", "Control"), class = "factor")), class = "data.frame", row.names = c(NA,
-10L))
Upvotes: 1
Views: 490
Reputation: 37903
My suggestion is to highjack the arrow
argument of geom_segment()
to serve as caps, since you've already precomputed the confidence intervals. You can control with an ifelse
whether to take the lower or higher confidence level. Example with dummy data below:
library(ggplot2)
# Make dummy data
df <- data.frame(
x = c(1:10, 1:10),
y = c(1:10, seq(0.5, 5, by = 0.5)),
type = rep(LETTERS[1:2], each = 10)
)
# Dummy confidence intervals
df$conf.hi <- df$y * 1.1
df$conf.lo <- df$y * 0.9
ggplot(df, aes(x, y, colour = type)) +
geom_line() +
geom_point() +
geom_segment(aes(xend = x,
yend = ifelse(type == "A", conf.hi, conf.lo)),
arrow = arrow(angle = 90))
Created on 2020-04-03 by the reprex package (v0.3.0)
EDIT: Example for added data
Probably, the reason that it didn't turn out as the example was because the conf.high
/conf.low
variables were not added to the prediction.
I used the std.error
instead of the conf.*
variables, as I noticed these are similar values.
I got a decent plot using the following.
ggplot(q2, aes(x, predicted, colour = group)) +
geom_line(aes(group = group)) +
geom_point() +
geom_segment(aes(xend = x,
yend = predicted + ifelse(group == "Intervention", std.error, -std.error)),
arrow = arrow(angle = 90))
Upvotes: 1