Warning Failed to apply `after_scale()` modifications to legend
Closed this issue · 6 comments
I'm receiving a warning when I attempt to build a plot that has three things:
- geom_rect
- a categorical axis
- a fill aesthetic
I would expect the following reproducible example to work. It does display the plot properly, but I always receive the following warning:
Warning message: Failed to apply after_scale()modifications to legend Caused by error: ! object 'ymin' not found
If I remove the fill aesthetic, the plot displays without the warning. I tried staging the fill aesthetic, but received the same results.
Reproducible example:
library(ggplot2)
data <- tibble::tibble(
Question = factor(c("Question A", "Question A", "Question A", "Question A", "Question A",
"Question B", "Question B", "Question B", "Question B", "Question B",
"Question C", "Question C", "Question C", "Question C", "Question C",
"Question D", "Question D", "Question D", "Question D", "Question D",
"Question E", "Question E", "Question E", "Question E", "Question E")),
Response = factor(c('Strongly disagree', 'Disagree', 'Neither agree nor disagree', 'Agree', 'Strongly agree',
'Strongly disagree', 'Disagree', 'Neither agree nor disagree', 'Agree', 'Strongly agree',
'Strongly disagree', 'Disagree', 'Neither agree nor disagree', 'Agree', 'Strongly agree',
'Strongly disagree', 'Disagree', 'Neither agree nor disagree', 'Agree', 'Strongly agree',
'Strongly disagree', 'Disagree', 'Neither agree nor disagree', 'Agree', 'Strongly agree')),
Min = c(0.5, 5.5, 8.5, 12.5, 15.5, -25.0, -4.0, 8.0, 13.0, 19.0, -3.0, 5.0, 7.0,
14.0, 19.0, -1.5, 8.5, 8.5, 12.5, 16.5, -16.0, -5.0, 10.0, 11.0, 26.0),
Max = c(5.5, 8.5, 12.5, 15.5, 17.5, -4.0, 8.0, 13.0, 19.0, 29.0, 5.0, 7.0, 14.0,
19.0, 23.0, 8.5, 8.5, 12.5, 16.5, 21.5, -5.0, 10.0, 11.0, 26.0, 33.0)
)
mapping <- aes(fill = Response,
xmin = Min,
xmax = Max,
ymin = stage(Question, after_scale = ymin - 0.3),
ymax = stage(Question, after_scale = ymax + 0.3))
plt <- ggplot(data = data) +
geom_rect(mapping = mapping) +
scale_y_discrete()
plt
#> Warning: Failed to apply `after_scale()` modifications to legend
#> Caused by error:
#> ! object 'ymin' not foundCreated on 2025-08-04 with reprex v2.1.1
Thanks for the report!
The legend replays the modified expressions, but the legend does not have access to a prior version of ymin as required for evaluating the expression.
Because this legend key doesn't use position aesthetics, this is a harmless case and ideally the warning could be omitted.
But, it is not harmless in all cases and distinguishing harmful from harmless is not straightforward because we don't know a priori which aesthetics a legend key needs.
I'm trying to develop a library of new geoms that depend on this behavior. Not many developers will be inclined to use my new library if it generates this harmless error every time. Is there some workaround or other approach?
@MichaelRFox If you're implementing geoms yourself you're probably better off not using stage() at all and instead making the required transformation somewhere in the relevant drawing code or writing a custom stat that performs the transformation.
Is there some workaround or other approach?
You can use get0() to deal with potential missingness, so you could do stage(Question, after_scale = get0("ymin", ifnotfound = 0) - 0.3). If you're writing a package, you can obfuscate the akwardness of that expression from your users.
I also agree that Claus' proposal is a more elegant solution.
In fact, for a package, I would expect that as the enduser I can just write aes(y = Question) and the geom figures out the rest. I shouldn't have to deal with ymin and ymax at all. There are plenty of geom examples to draw from for inspiration, such as geom_bar().
Thank you for all your comments.
