Skip to content

Circumventing scales #5142

Closed
Closed

Description

@teunbrand

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions