Reputation: 312
I have some data where some estimates have wide error bars. I'd like to plot on a meaningful scale by setting limits to the graph. However, I'd also like to indicate where error bars exceed the limits. Preferably with an arrow, and if possible, without using geom_segment
, as it doesn't seem to play nicely with the log10 scale. Below the red arrows are drawn in afterwards. The solution would be to add arrows or other indication where geom_errorbar
exceeds plot limits within ggplot.
set.seed(12345)
data <- data.frame(A = rnorm(10),
group = c(rep("Dog", 5), rep("Cat", 5)),
Time = c(rep(1:5), rep(1:5)))
data <- data %>% mutate(
SE = abs(rnorm(10)),
B = A + SE,
C = A - SE
)
upper <- (with(data, max(B)) - 0.5) %>% exp()
lower <- (with(data, min(C)) + 0.5) %>% exp()
data <- data %>% mutate_at(vars(A, B, C), funs(exp))
library (ggplot2)
ggplot(data = data, aes(y = A, x = Time, color = group)) +
geom_point(position = position_dodge(width = 0.2), size = 2) +
geom_errorbar(aes(ymin = C, ymax = B), position = "dodge", width = 0.2, size = 0.8) +
coord_cartesian(ylim = c(lower, upper)) +
scale_y_log10()
Upvotes: 3
Views: 1017
Reputation: 312
I found a not-so-precise solution. You can call geom_point once for upward directed triangles, and again for downward facing triangles. The only problem is that coord_cartesian doesn't seem to set the limits exactly at the specified values, so you have to add or subtract to each limit to get the triangle in the right position. Additionally, since position_dodge is already being used, position_nudge is unavailable. It involves guessing the the values to add or subtract to the y coordinate of the geom_point.
PLEASE comment if there's better solution.
library(ggplot2)
library(tidyverse)
set.seed(12345)
data <- data.frame(A = rnorm(10),
group = c(rep("Dog", 5), rep("Cat", 5)),
Time = c(rep(1:5), rep(1:5)))
data <- data %>% mutate(
SE = abs(rnorm(10)),
B = A + SE,
C = A - SE
)
upper <- (with(data, max(B)) - 0.5) %>% exp()
lower <- (with(data, min(C)) + 0.5) %>% exp()
data <- data %>% mutate_at(vars(A, B, C), funs(exp))
data <- data %>%
mutate(upper_out = ifelse(B > upper, upper, NA),
lower_out = ifelse(C < lower, lower, NA))
ggplot(data = data, aes(y = A, x = Time, color = group, fill = group)) +
geom_point(position = position_dodge(width = 0.2), size = 2) +
geom_errorbar(aes(ymin = C, ymax = B), position = "dodge", width = 0.2, size = 0.8) +
geom_point(aes(y = upper_out + 1.02), shape = 24,
position = position_dodge(width = 0.2), size = 4, show.legend = F) +
geom_point(aes(y = lower_out - 0.013), shape = 25,
position = position_dodge(width = 0.2), size = 4, show.legend = F) +
scale_y_log10() +
coord_cartesian(ylim = c(lower, upper))
Upvotes: 1