Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusing warning in geom_segment() with length 1 aesthetics #5762

Closed
DanChaltiel opened this issue Mar 7, 2024 · 8 comments · Fixed by #5799
Closed

Confusing warning in geom_segment() with length 1 aesthetics #5762

DanChaltiel opened this issue Mar 7, 2024 · 8 comments · Fixed by #5799
Labels
messages requests for improvements to error, warning, or feedback messages
Milestone

Comments

@DanChaltiel
Copy link

Hi,

In the latest version, a warning is thrown if aesthetics are length 1 while the data is not, hinting to use annotate() instead of a geom.

Of note, I could have missed it but I couldn't find this change in NEWS.

While this warning should be legitimate in most cases, there are some where it does not make much sense and that annotate() is not usable, in my case when using geom_segment() with summary functions.

It is thrown in the documentation (https://ggplot2.tidyverse.org/reference/aes_position.html).

One could argue that the documentation example could indeed be replaced with annotate(), so here is an example that cannot:

library(ggplot2) 
ggplot(mtcars) +
  aes(x=mpg, y=disp) +
  geom_point() +
  geom_segment(aes(x=min(mpg), xend=max(mpg), y=min(disp), yend=max(disp)))
#> Warning in geom_segment(aes(x = min(mpg), xend = max(mpg), y = min(disp), : All aesthetics have length 1, but the data has 32 rows.
#> i Did you mean to use `annotate()`?

ggplot(mtcars) +
  aes(x=mpg, y=disp) +
  geom_point() +
  annotate("segment", x=min(mpg), xend=max(mpg), y=min(disp), yend=max(disp))
#> Error in FUN(X[[i]], ...): only defined on a data frame with all numeric-alike variables

Created on 2024-03-07 with reprex v2.1.0

@teunbrand
Copy link
Collaborator

teunbrand commented Mar 11, 2024

Argueably, the example you raise should also be annotate(). The main difference is that you're using aes() to use non-standard evaluation in geom_segment(), whereas you'd have to use standard evaluation in annotate(), e.g. do x = min(mtcars$mpg).

The warning can also be surpressed by providing data of the correct size, like data = ~ head(.x, 1).

@DanChaltiel
Copy link
Author

DanChaltiel commented Mar 12, 2024

@teunbrand Using standard evaluation like in your example implies using the table name (mtcars), so we cannot pipe into ggplot().

Thanks for the tip about warning suppressing :-) Feels a bit hacky but it works fine

@teunbrand
Copy link
Collaborator

There are plenty of things that are not really pipeable for ggplot2, for example setting scale parameters, so preserving pipeability is only a minor concern. The proper way to go about this is implementing #3501 I guess, where you could arbitrarily summarise the data.

@teunbrand teunbrand added the messages requests for improvements to error, warning, or feedback messages label Mar 21, 2024
@clauswilke
Copy link
Member

I'm just seeing this for the first time, coming from #5797.

I feel it's important to highlight what exactly is going wrong here and in #5797. While the plot may look fine, it is not. The geom that triggers the warning is drawn over and over again, as many times as the data is duplicated. You can see this if you try to make the geom transparent. We used to get bug reports about problems with transparency all the time and it was always this issue.

I would strongly advise against suppressing the warning. Instead, fix the code so you actually draw only one line.

@teunbrand The actionable item here is maybe to improve the warning, instead of just saying "did you mean to use annotate()". Clearly people don't understand what the issue is.

library(ggplot2) 
ggplot(mtcars) +
  aes(x=mpg, y=disp) +
  geom_point() +
  geom_segment(
    aes(x=min(mpg), xend=max(mpg), y=min(disp), yend=max(disp)),
    alpha = 0.1, # should result in a transparent line
    linewidth = 5
  )
#> Warning in geom_segment(aes(x = min(mpg), xend = max(mpg), y = min(disp), : All aesthetics have length 1, but the data has 32 rows.
#> ℹ Did you mean to use `annotate()`?

Created on 2024-03-24 with reprex v2.0.2

@teunbrand
Copy link
Collaborator

Yeah I agree with Claus that the warning is there for good reason.
Maybe something along the lines of:

Drawing 32 duplicates of the layer, as aesthetics of length 1 are recycled to match the data.
Did you mean to use annotate()?

The examples in the docs should be fixed, either by providing the data in the correct shape or using annotate().

@clauswilke
Copy link
Member

I think the point is that people that run into this issue generally do not want to use annotate(). So maybe write something like "Please consider using annotate() or alternatively provide this layer with its own data set."

@DanChaltiel
Copy link
Author

Drawing 32 duplicates of the layer, as aesthetics of length 1 are recycled to match the data.

Sorry if my comment is out of line (I don't understand ggplots internals at all), but is recycling aesthetics of any length ever a good thing?

@teunbrand
Copy link
Collaborator

Recycling happens following the tidyverse rules (either length == 1 or length == nrow(data)).
Recycling aesthetics of length 1 is useful in constructing a layer-based scale (opposite to the typical data-based scale).

library(ggplot2)

ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(colour = "points")) +
  geom_smooth(aes(colour = "line"))
#> `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Created on 2024-03-28 with reprex v2.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
messages requests for improvements to error, warning, or feedback messages
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants