Skip to content

Warn about ignored scales and guides #6032

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

Closed
wants to merge 9 commits into from

Conversation

teunbrand
Copy link
Collaborator

This PR aims to fix #3743 and guides indentified in #3196 (comment).

Briefly, when using a scale or guide for an aesthetic that is not in use, you'll get a warning.

Implementation-wise, it wasn't too straightforward to allow guides and scales to assess their usage. A few remarks on this in the code.

An example:

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

ggplot(mpg, aes(displ, hwy, colour = drv)) +
  geom_point() +
  scale_fill_discrete() +
  guides(shape = "bar")
#> Warning: Ignoring unknown guide: "shape".
#> Warning: Ignoring scale for unused aesthetics: "fill".

Created on 2024-08-07 with reprex v2.1.1

@@ -354,15 +354,15 @@ Layer <- ggproto("Layer", NULL,

compute_statistic = function(self, data, layout) {
if (empty(data))
return(data_frame0())
return(data)
Copy link
Collaborator Author

@teunbrand teunbrand Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this file, 0-row data still contains relevant information in terms of column names, so we don't return 0-column data here.

Comment on lines +105 to +107
npscales$train(data)
plot$guides <- plot$guides$build(npscales, plot$layers, plot$labels, data)
data <- npscales$map(data, layers)
Copy link
Collaborator Author

@teunbrand teunbrand Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to warn about guides when there are no non-position scales, the guide building needed to be executed unconditionally. The npscales$n() == 0 condition is handled in new <ScalesList> methods.

train_df = function(self, df, drop = FALSE) {
if (empty(df) || length(self$scales) == 0) {
return()
}
lapply(self$scales, function(scale) scale$train_df(df = df))
},

map = function(self, data, layers) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really a fan of this as layers and scales should ideally be separate on only interact through the data, but I haven't found a better way around this.


known <- unique(unlist(c(
lapply(data, colnames),
lapply(layers, function(x) names(x$computed_mapping))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes you can have a mapping like colour = after_scale(alpha(fill, 0.3)) that isn't instantiated as a column in the data yet. In order to not warn about these, we need to access the layer's mapping.

Comment on lines -140 to -149
built <- ggplot_build(p)
plot <- built$plot
guides <- guides_list(plot$guides)
guides <- guides$build(
plot$scales,
plot$layers,
plot$labels
)
expect_length(ggplot_build(p)$plot$guides$guides, 0)

p <- ggplot(mpg, aes(cty, hwy, colour = class)) +
geom_point() +
guides(colour = guide_none())

expect_length(guides$guides, 0)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test wasn't testing what is was supposed to be testing.

Comment on lines +954 to +955
guides(size = guide_legend(order = 2),
color = guide_colorbar(order = 1)) +
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This plot wasn't using the shape aesthetic, so the test was wrong. The checks in this PR correctly picked up on this.

@thomasp85
Copy link
Member

This seems surprisingly complicated. Isn't there a point in the build process where all mapped aesthetics are known and we can check that list against the provided scales and guides?

@teunbrand
Copy link
Collaborator Author

Agree that it is more complicated than one'd hope. The reason that the approach you outline doesn't currently work is because Stat$default_aes does not get absorbed into the computed mapping. For example StatSum$default_aes has an after-stat default for size, a size scale is correctly initialised, but there is no size mapping, so we'd spuriously warn in this case.

@teunbrand teunbrand marked this pull request as draft September 11, 2024 09:23
@teunbrand teunbrand marked this pull request as draft September 11, 2024 09:23
@teunbrand teunbrand marked this pull request as draft September 11, 2024 09:23
@teunbrand teunbrand marked this pull request as draft September 11, 2024 09:23
@teunbrand teunbrand marked this pull request as draft September 11, 2024 09:23
@teunbrand
Copy link
Collaborator Author

I'm giving up on this, this is too complicated to be worth it.

@teunbrand teunbrand closed this Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: warning for fill/colour mismatch between aes() and scale...()
2 participants