Dynamically create expression for ggplot legend?

1.3k views Asked by At

I want to plot a line graph, with multiple lines, coloured depending on a grouping variable. Now I want to set the legend labels via scale-command:

scale_color_manual(values = colors_values, labels = ...)

The legend labels are as following: "x^2", "x^3", "x^4" etc., where the range is dynamically created. I would now like to dynamically create the expression as label text, i.e.

  • "x^2" should become x2
  • "x^3" should become x3

etc.

The amount of legend labels varies, so I thought about something like as.expression(sprintf("x^%i", number)), which does of course not work as label parameter for the scale function.

I have searched google and stack overflow, however, I haven't found a working solution yet, so I hope someone can help me here.

Here's a reproducible example:

poly.term <- runif(100, 1, 60)
resp <- rnorm(100, 40, 5)
poly.degree <- 2:4
geom.colors <- scales::brewer_pal(palette = "Set1")(length(poly.degree))
plot.df <- data.frame()
for (i in poly.degree) {
  mydat <- na.omit(data.frame(x = poly.term, y = resp))
  fit <- lm(mydat$y ~ poly(mydat$x, i, raw = TRUE))
  plot.df <- rbind(plot.df, cbind(mydat, predict(fit), sprintf("x^%i", i)))
}
colnames(plot.df) <- c("x","y", "pred", "grp")
ggplot(plot.df, aes(x, y, colour = grp)) +
  stat_smooth(method = "loess", se = F) +
  geom_line(aes(y = pred))
  scale_color_manual(values = geom.colors
                     # here I want to change legend labels
                     # lables = expresion???
                     )

enter image description here

I would like to have the legend labels to be x2, x3 and x4.

1

There are 1 answers

0
Roland On BEST ANSWER
ggplot(plot.df, aes(x, y, colour = grp)) +
  stat_smooth(method = "loess", se = F) +
  geom_line(aes(y = pred)) +
  scale_color_manual(values = setNames(geom.colors,
                                       paste0("x^",poly.degree)),
                     labels = setNames(lapply(poly.degree, function(i) bquote(x^.(i))), 
                                       paste0("x^",poly.degree)))

It's important to ensure correct mapping if you change values or labels in the scale. Thus, you should always use named vectors.

resulting plot