Description
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 notGeom$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 usescale_size_identity()
simultaneously in order to construct a legend. While I'm not certain it poses a problem, but we might discourage this by havingscale_*_identity()
explicitly warn when it seesAsIs
objects.
Ambiguities:
- There is no
scale_{x/y}_identity()
, so what should happen if people useaes(x = I(var))
? Should they be interpreted asnpc
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.