-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Default pointshape
of 19 can cause confusion with fill guides
#6177
Comments
Here's a minimal implementation of the warning that I don't love since it's very noisy: 697002311 (HEAD -> warn_unfilled_point) [3 minutes ago, Carl Suster]
Warn if point key incompatible with fill
diff --git a/R/geom-point.R b/R/geom-point.R
index 3efa394c3..51a285cd8 100644
--- a/R/geom-point.R
+++ b/R/geom-point.R
@@ -236,3 +236,11 @@ translate_shape_string <- function(shape_string) {
unname(pch_table[shape_match])
}
+
+is_filled_shape <- function(shape) {
+ if (is.character(shape)) {
+ shape <- translate_shape_string(shape)
+ }
+
+ shape %in% 21:25
+}
diff --git a/R/guide-legend.R b/R/guide-legend.R
index 37aad2e3f..37f267fe0 100644
--- a/R/guide-legend.R
+++ b/R/guide-legend.R
@@ -237,6 +237,7 @@ GuideLegend <- ggproto(
matched_aes <- matched_aes(layer, params)
key <- params$key[matched_aes]
key$.id <- seq_len(nrow(key))
+ key$.aesthetics <- list(matched_aes)
# Filter static aesthetics to those with single values
single_params <- lengths(layer$aes_params) == 1L
diff --git a/R/legend-draw.R b/R/legend-draw.R
index ccfb03587..aced22a7d 100644
--- a/R/legend-draw.R
+++ b/R/legend-draw.R
@@ -24,6 +24,14 @@ NULL
#' @export
#' @rdname draw_key
draw_key_point <- function(data, params, size) {
+ fill_wanted <- mapply(\(a) "fill" %in% a, data$.aesthetics)
+ if (fill_wanted && !is_filled_shape(data$shape)) {
+ cli::cli_warn(c(
+ "Drawing guide for fill with unfilled shape {data$shape}",
+ "i" = "Consider overriding the key shape for the fill scale like {.code guides(fill = guide_legend(override.aes = list(shape = 'circle filled')))}"
+ ))
+ }
+
if (is.null(data$shape)) {
data$shape <- 19
} else if (is.character(data$shape)) { It adds The warning might only apply to some keys (e.g. when the fill guide includes both filled and unfilled shapes), so it has to be checked for each key. The duplicate warnings are excessive though so it would be better to group them and/or have a way to suppress the warning altogether. In actiondevtools::load_all("~/code/ggplot2")
#> ℹ Loading ggplot2
ggplot(head(diamonds, n = 20)) +
geom_point(aes(carat, price, fill = cut, shape = color, size = cut)) +
scale_shape_manual(values = 21:25)
#> Warning: Drawing guide for fill with unfilled shape 19
#> ℹ Consider overriding the key shape for the fill scale like `guides(fill =
#> guide_legend(override.aes = list(shape = 'circle filled')))`
#> Drawing guide for fill with unfilled shape 19
#> ℹ Consider overriding the key shape for the fill scale like `guides(fill =
#> guide_legend(override.aes = list(shape = 'circle filled')))`
#> Drawing guide for fill with unfilled shape 19
#> ℹ Consider overriding the key shape for the fill scale like `guides(fill =
#> guide_legend(override.aes = list(shape = 'circle filled')))`
#> Drawing guide for fill with unfilled shape 19
#> ℹ Consider overriding the key shape for the fill scale like `guides(fill =
#> guide_legend(override.aes = list(shape = 'circle filled')))`
#> Drawing guide for fill with unfilled shape 19
#> ℹ Consider overriding the key shape for the fill scale like `guides(fill =
#> guide_legend(override.aes = list(shape = 'circle filled')))` ggplot(head(diamonds, n = 20)) +
geom_point(aes(carat, price, fill = cut, shape = color, size = cut)) +
guides(fill = guide_legend(override.aes = list(shape = 'circle filled'))) +
scale_shape_manual(values = 21:25) Created on 2024-11-06 with reprex v2.1.1 |
Hi there thanks for the report! We appreciate the time you put in building reproducible examples and exploring possible solutions.
Regarding some of the specifics:
This is true for
The fill scale should be ignorant of other scales, so yes, it should ignore the actual values of your shape scale. It should obey
Ideally we don't want to hardcode around the |
Ah sorry I missed the earlier report. Please feel free to close this if your stance hasn't changed :) My motivation is just that I ran into this scenario while helping someone and it took me quite a while to work out what was going on even though in hindsight it's clear why it behaves that way. It's really surprising to see a guide where the key can't represent the aesthetic that it's supposed to be explaining. A warning could help someone else discover the solution faster. Anecdotally, filled points are less "advanced" than might be expected because there are code snippets out there advocating for them (e.g. here, here, here). I've seen people who know about filled shapes but are less familiar with how guides work, so aren't able to debug the guide so fall back on fixing colour in Illustrator or similar.
Good point. I only mentioned this because my first attempt was to override the default shape in
I agree that makes sense as a ggplot axiom. In specific cases it might not be the best result, but that's what
I thought that by this stage we were close enough to the Initially I thought this might be an instance of a more generic problem of guides not being able to represent their intended aesthetic, but on reflection it might just be confined to |
Extension packages can use variants of
Yes I think this would be the right to do. Having an example for |
Occasionally it can be useful to use filled shapes (i.e. in the range
21:25
) to separately control the colour and fill aesthetics ingeom_point()
. Here's a contrived example using shape 21 that works:Now if we also map the shape aesthetic, the fill guide draws the keys using its default shape of 19 which doesn't support fill leading to the colours disappearing from the legend:
It can of course be fixed by overriding the shape to be 21 as in the first example:
Created on 2024-11-06 with reprex v2.1.1
This isn't really a bug because it's behaving as intended, but it's still a bit surprising! Some possible solutions:
key_glyph = "point"
, a non-empty/non-constant fill, and an unfilled shape.Note that even though
draw_key_point()
fills in a default of 19 that doesn't seem relevant in practice because the key is always draw with a non-NULL
value determined by the theme'spointshape
if shape isn't mapped for a guide.Aside: using a key glyph outside shape scale
Even putting aside filled shapes, if my shape scale is only triangles and squares, should any of the guides really be using circles for the keys? I suspect that by now people are used to thinking of circles as the "neutral" point shape in ggplot.Created on 2024-11-06 with reprex v2.1.1
The text was updated successfully, but these errors were encountered: