Error bars and lines do not match in ggplot2

Viewed 182

I have a problem with error bars in ggplot2.

I want to plot an interaction between continuous [iv] and nominal [condition] variable. I use such a code

iv = runif(n = 100, min = 1, max = 7)
condition <- rep(letters[1:2], length.out = 100)
y = runif(n = 100, min = 1, max = 100)

df <- data.frame(iv, condition, y)

lm20 <- lm(y ~ condition * iv, data = df)
summary(lm20) 

df$condition <- as.factor(df$condition)

ggeffect(lm20, terms = c("condition", "iv")) %>%  
  plot(show.title = FALSE) + 
  stat_summary(fun.y = mean,
               geom = "point") +
  stat_summary(fun.y = mean,
               geom = "line") +
  stat_summary(fun.data = mean_cl_boot,
               geom = "errorbar") +
  scale_y_continuous("Voting intentions", limits = c(0, 100)) + 
  scale_colour_discrete(name = "Control", labels = c("Low", "Medium", "High")) +
  scale_x_discrete("Condition", labels = c("Low","High")

And this is what I get:

graph

I encounter two problems

  1. Error bars and lines do not match
  2. I cannot change the labels on the X axis
2 Answers

Below is a solution using solely ggplot2, so not as elegant... See if it does the trick!

# Create data frame with the effects    
df <- as.data.frame(ggeffect(lm20, terms = c("condition", "iv")))
# Add coordinates manually
df$x2 <- rep(1:2, 3) + rep(c(-.1,0,.1), each = 2)

# Plot
ggplot(df, aes(x2, predicted, col = group)) + 
  geom_errorbar(aes(x = x2, ymin = predicted-std.error, ymax = predicted+std.error), width = .1) +
  geom_segment(df %>% pivot_wider(id_cols = group, names_from = x,  values_from = c(predicted:conf.high, x2)),
               mapping = aes(x = x2_a, xend = x2_b, y = predicted_a, yend = predicted_b)) +
  geom_point(size = 2) +
  scale_color_discrete("Control",c("#9b2756", "#003054","#66b0a5"), labels=c("Low", "Medium", "High")) +
  scale_y_continuous("Voting intentions", limits = c(0, 100)) + 
  scale_x_continuous("Condition", breaks = 1:2, labels = c("Low","High"))

Here is the result: enter image description here

There are a couple of things going on here. Mainly:

  • you need to set a position_dodge that displaces your added points by the same amount as ggeffects is already displacing the error bars
  • ggeffects is actually using a continuous x-axis scale. See my use of scale_x_continuous() below ...
  • mean_cl_boot doesn't seem to be doing anything, haven't quite figured out why
library(ggeffects)
library(ggplot2)
library(magrittr)

pd <- position_dodge(width=0.25)  ## width set by trial & error to match ggeffects plot
ggeffect(lm20, terms = c("condition", "iv")) %>%  
    plot(show.title = FALSE) +
    ## set large size/alpha to distinguish mean points from the 
    ##   (identical) points that ggeffects is already using for the estimated values
    stat_summary(fun = mean, geom = "point", position = pd, size = 5,
                 alpha=0.5) +
    stat_summary(fun = mean, geom = "line", position = pd) +
    stat_summary(fun.data = mean_cl_boot, geom = "errorbar",
                 position = pd, size = 5, alpha=0.5) +
    scale_y_continuous("Voting intentions", limits = c(0, 100)) + 
    scale_colour_discrete(name = "Control", labels = c("Low", "Medium", "High")) +
    scale_x_continuous(name = "Condition",
                       breaks = 1:2,
                       labels = c("Low","High"))
Related