Why does ggplot legend not display some categories when color is mapped conditionally?
15:15 07 Oct 2025

I’m trying to create an admittedly highly complicated coefficient plot in ggplot where points are colored by outcome, but are grayed out when non-significant at p<.10 and are "faded" between .05 and .10.

However, when I map color conditionally based on the alpha and gray significance, the ggplot legend only shows the outcomes that have at least one significant result...the non-sig ones drop out of the legend. How can I force them to be displayed?

I've attempted to create a MRE below because the full code has a ton of complexity and formatting that isn't relevant, and my data are restricted, but I can just show the entirety of the real code if needed.

set.seed(100)
library(ggplot2)
library(dplyr)
library(tidyr)

df <- expand_grid(
  outcome   = paste0("out", 1:4),
  treatment = c("trt1", "trt2"),
  moderator = c("mod1", "mod2")
) %>%
  mutate(
    estimate = rnorm(n(), 0.06, 0.02),
    se       = runif(n(), 0.01, 0.02),
    ci_lo    = estimate - 1.96 * se,
    ci_hi    = estimate + 1.96 * se,
    p_value  = case_when(
      outcome == "out1" ~ 0.25,
      outcome == "out2" ~ 0.08,
      outcome == "out3" ~ 0.20,
      outcome == "out4" ~ 0.01)
  )


ggplot(df, aes(x = estimate, y = moderator,
  color = ifelse(p_value > 0.10, "gray50", outcome),
  shape = ifelse(p_value > 0.10, "gray50", outcome),
  alpha = ifelse(p_value <= 0.05, 1,
           ifelse(p_value <= 0.10, 0.5, 0.3)),
  group = outcome)) +
  geom_errorbarh(aes(xmin = ci_lo, xmax = ci_hi),
                 height = 0, position = pd) +
  geom_point(size = 2.5, position = position_dodge(width = 0.5)) +
  facet_grid(~ treatment) +
  scale_color_manual(
    values = c(out1 = "red", out2 = "orange",
               out3 = "blue", out4 = "green",
               gray50 = "gray50"),
    breaks = c("out1","out2","out3","out4"),
    name = "Outcome") +
  scale_shape_manual(
    values = c(out1 = 17, out2 = 16,
               out3 = 17, out4 = 16,
               gray50 = 4),
    breaks = c("out1","out2","out3","out4"),
    name = "Outcome") +
  scale_alpha_identity() +
  theme_classic()
r ggplot2