I've created some boxplots with confidence intervals using geom_crossbar. The issue is that I'd like the horizontal mean lines to extend horizontally beyond the boxes a bit -- this is apparently not possible within geom_crossbar.
I am using geom_segment as a way to extend the mean lines with an overlay. It's sort of working, but the mean line for one of the fill variable levels is too short (m) and the other level line (f) is too long. Any help is much appreciated. Reprex below.
library(tidyverse)
sex <- c('f','m','f','m')
pet <- c('cat', 'cat', 'dog', 'dog')
mean <- c(4, 4.2, 5, 4.5)
ci_upper <- c(4.2, 4.4, 5.1, 4.7)
ci_lower <- c(3.8, 4.0, 4.9, 4.3)
df <- data.frame(sex, mean, ci_upper, ci_lower) %>%
mutate(pet = as.factor(pet))
ggplot(data = df, aes(x = pet, y = mean, fill = sex)) +
geom_crossbar(aes(ymin = ci_lower, ymax = ci_upper),
position = position_dodge(width = 1.2)) +
geom_segment(aes(x = as.numeric(pet) - 0.3,
xend = as.numeric(pet) + 0.3,
y = mean, yend = mean),
position = position_dodge(width = 1.2),
color = "red", size = 2)
I've created some boxplots with confidence intervals using geom_crossbar. The issue is that I'd like the horizontal mean lines to extend horizontally beyond the boxes a bit -- this is apparently not possible within geom_crossbar.
I am using geom_segment as a way to extend the mean lines with an overlay. It's sort of working, but the mean line for one of the fill variable levels is too short (m) and the other level line (f) is too long. Any help is much appreciated. Reprex below.
library(tidyverse)
sex <- c('f','m','f','m')
pet <- c('cat', 'cat', 'dog', 'dog')
mean <- c(4, 4.2, 5, 4.5)
ci_upper <- c(4.2, 4.4, 5.1, 4.7)
ci_lower <- c(3.8, 4.0, 4.9, 4.3)
df <- data.frame(sex, mean, ci_upper, ci_lower) %>%
mutate(pet = as.factor(pet))
ggplot(data = df, aes(x = pet, y = mean, fill = sex)) +
geom_crossbar(aes(ymin = ci_lower, ymax = ci_upper),
position = position_dodge(width = 1.2)) +
geom_segment(aes(x = as.numeric(pet) - 0.3,
xend = as.numeric(pet) + 0.3,
y = mean, yend = mean),
position = position_dodge(width = 1.2),
color = "red", size = 2)
Share
Improve this question
edited Mar 16 at 2:07
r2evans
162k7 gold badges86 silver badges168 bronze badges
Recognized by R Language Collective
asked Mar 16 at 0:51
wythe4wythe4
1391 silver badge9 bronze badges
2 Answers
Reset to default 2You can draw your mean lines more easily using a second geom_crossbar
where
I use the width
parameter to add some padding for both (instead of setting a width > 1 in position_dodge
). I also added show.legend=FALSE
to the second geom_crossbar
to drop it from the legend.
library(ggplot2)
pd <- position_dodge(width = .9)
ggplot(data = df, aes(x = pet, y = mean, fill = sex)) +
geom_crossbar(aes(ymin = ci_lower, ymax = ci_upper),
position = pd, width = 0.8
) +
geom_crossbar(
aes(ymin = mean, ymax = mean),
position = pd, width = 0.85, color = "red",
show.legend = FALSE
)
I think it is easier to make a new column in your data frame to set the position of the line segment rather than trying to adjust relative to what position_dodge does.
library(tidyverse)
sex <- c('f','m','f','m')
pet <- c('cat', 'cat', 'dog', 'dog')
mean <- c(4, 4.2, 5, 4.5)
ci_upper <- c(4.2, 4.4, 5.1, 4.7)
ci_lower <- c(3.8, 4.0, 4.9, 4.3)
W <- 1.2
df <- data.frame(sex, mean, ci_upper, ci_lower) %>%
mutate(pet = as.factor(pet),
X = as.numeric(pet) + ifelse(sex == 'f', -W/4, W/4))
ggplot(data = df, aes(x = pet, y = mean, fill = sex)) +
geom_crossbar(aes(ymin = ci_lower, ymax = ci_upper),
position = position_dodge(width = W)) +
geom_segment(aes(x = X - W/4,
xend = X + W/4,
y = mean, yend = mean),
#position = position_dodge(width = 1.2),
color = "red", size = 2)