tidyverse/ggplot2

expressions as annotations broken

Closed this issue · 12 comments

I think this is due to the recent update. It used to work.

library(ggplot2)
ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() +
  annotate("text", x = 3, y = 30, label = latex2exp::TeX("$\\alpha + \\beta x$"))
#> Error in `annotate()`:
#> ! Problem while setting up geom aesthetics.
#> ℹ Error occurred in the 2nd layer.
#> Caused by error in `list_sizes()` at ggplot2/R/geom-.R:518:3:
#> ! `x$label` must be a vector, not a <latexexpression/expression> object.

Created on 2025-09-18 with reprex v2.1.1

Thanks for the report! The error message is correct, it should be a proper vector. Previously, the expressions were allowed by mistake. The parse argument should be used if the intent is to use an expression.

OK, but the parse argument doesn't seem to make any difference.

It seems latex2exp::TeX() can return characters by output = "character". It's a bit inconvenient, but I hope this works for you...

Thanks. In case anyone else has the same problem, the solution was a combination of these suggestions:

library(ggplot2)

ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  annotate(
    "text",
    x = 3,
    y = 30,
    label = latex2exp::TeX("$\\alpha + \\beta x$", output = "character"),
    parse = TRUE,
    size = 5
  )

Created on 2025-09-19 with reprex v2.1.1

Does anyone have a solution for axis labels?

ggplot(mtcars, aes(x = wt, y = mpg)) +
    geom_point() +
    annotate(
        "text",
        x = 3,
        y = 30,
        label = latex2exp::TeX("$\\alpha + \\beta x$", output = "character"),
        parse = TRUE,
        size = 5
    ) +
    scale_x_continuous(breaks = 3, labels = TeX("$\\alpha$"))

yields

Error in vec_size():
! x must be a vector, not a <latexexpression/expression> object.

ggplot(mtcars, aes(x = wt, y = mpg)) +
    geom_point() +
    annotate(
        "text",
        x = 3,
        y = 30,
        label = latex2exp::TeX("$\\alpha + \\beta x$", output = "character"),
        parse = TRUE,
        size = 5
    ) +
    scale_x_continuous(breaks = 3, labels = TeX("$\\alpha$", output = character), parse = TRUE)

yields:
Error in scale_x_continuous(breaks = 3, labels = TeX("$\alpha$", output = character), :
unused argument (parse = TRUE)

Thanks, confirmed. Could you file a new issue? It seems this is so tricky that I cannot immediately come up with a good fix.

The error happens here. key is a data frame containing a latexexpression object in .label column.

key <- vec_slice(key, is.finite(oob_censor_any(breaks, range)))

The problem is, the latexexpression object cannot be subset by vec_slice() because

x <- as.list(latex2exp::TeX("$\\alpha$"))
vctrs::obj_is_vector(x)
#> [1] FALSE

However, it works if the object doesn't have S3 classes.

vctrs::obj_is_vector(unclass(x))
#> [1] TRUE

So, an easy workaround is to use unclass(). Or, you can simply use parse(text =) instead of latex2exp.

library(ggplot2)

ggplot(mtcars, aes(x = wt, y = mpg)) +
    geom_point() +
    annotate(
        "text",
        x = 3,
        y = 30,
        label = latex2exp::TeX("$\\alpha + \\beta x$", output = "character"),
        parse = TRUE,
        size = 5
    ) +
    scale_x_continuous(breaks = 3, labels = unclass(latex2exp::TeX("$\\alpha$")))

Created on 2025-09-23 with reprex v2.1.1

Thanks for the report! The error message is correct, it should be a proper vector. Previously, the expressions were allowed by mistake. The parse argument should be used if the intent is to use an expression.

This has to be the worst change ever.

This has to be the worst change ever.

And yet, we have no plans to revert it.

And yet, we have no plans to revert it

However, plans change and now we want to allow expressions as label aesthetic.

And yet, we have no plans to revert it

However, plans change and now we want to allow expressions as label aesthetic.

My workaround has been to use expr_text() around expression() and bqoute(). Saved me from having to remake literally hundreds of graphs and figures.

for reference, here is an updated version of my code to plot (1) axis labels in scientific notation in 10^x format; (2) latitude-longitude labels. For a character vector v I had to change parse(text=v) to sapply(v, function(x) parse(text = x)) (it would be convenient if scale_[xy]_continuous got a parse argument ...)

https://gist.github.com/bbolker/5ba6a37d64b06a176e320b2b696b6733