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

Circumventing scales #5142

Closed
teunbrand opened this issue Jan 9, 2023 · 0 comments · Fixed by #5477
Closed

Circumventing scales #5142

teunbrand opened this issue Jan 9, 2023 · 0 comments · Fixed by #5477

Comments

@teunbrand
Copy link
Collaborator

teunbrand commented Jan 9, 2023

To recap the discussion of #4821, passing (unmapped) aesthetics with length > 1 outside aes() is not ideal. However, it is currently necessary to bypass mapping values to a scale. Hence, there seems to be a need to pass values parallel to the data that circumvent scales, that isn't passed outside aes().

This brings us to a discussion about what we can do to more formally support circumventing scales. In #4821 (comment), I suggested that scales should ignore AsIs objects / I() input.

The current state is that the scale type for AsIs objects default to scale_*_identity(). In simple situations, the AsIs class already does what we want: we don't want to map it to a scale, so we use the identity scale to keep the values verbatim. The problem with this situation arises when another mapping, in another layer, does require a non-identity scale. There are no solutions for this problem in vanilla ggplot2.

Because there is a need to pass verbatim values, doing so outside aes() is discouraged, and the identity scale solution has unacceptable drawbacks, I think it might make sense to have scales explicitly ignore AsIs objects.

Here are the upsides:

  • The semantic meaning of I() would change very little. It still means 'pass these values verbatim'.
  • They are proper aesthetics, so data parallelism would be ensured (Mismatched fill colour with geom_dotplot #4821) because they're evaluated during Layer$compute_aesthetics() and not Geom$use_defaults().
  • No need for scale_*_identity() to get involved, so no clashes with other scales.

The drawbacks are:

  • Need to rewrite scale methods to ignore AsIs objects on purpose, which might have some small overhead.
  • There might be a rare case in which people redundantly specificy e.g. aes(size = I(value)) and use scale_size_identity() simultaneously in order to construct a legend. While I'm not certain it poses a problem, but we might discourage this by having scale_*_identity() explicitly warn when it sees AsIs objects.

Ambiguities:

  • There is no scale_{x/y}_identity(), so what should happen if people use aes(x = I(var))? Should they be interpreted as npc units between 0-1, just like after coord transformation? Should they just behave as regular positions?
  • What should the effect of AsIs objects be on automatic grouping? Intuitively, I think it should be inert.

I'd be happy to discuss, and, if people see some merit in this, prepare a PR to explore implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant