mjskay / ggdist

Visualizations of distributions and uncertainty
https://mjskay.github.io/ggdist/
GNU General Public License v3.0
849 stars 26 forks source link

base ggplot2 key glyphs don't know about aesthetic overrides #134

Open Ari04T opened 2 years ago

Ari04T commented 2 years ago

Hello

ggplot2 seems to allow the modification of the key glyph by using the key_glyph parameter inside a geom or stat.

An example is:

p <- ggplot(economics, aes(date, psavert, color = "savings rate"))
# key glyphs can be specified by their name
p + geom_line(key_glyph = "timeseries")

If I try to do this with ggdist, I get an error.

mtcars %>% 
    ggplot(aes(x = mpg, y = as.factor(cyl))) +
    stat_slab(aes(fill = as.factor(cyl)),
              key_glyph = "timeseries")
Error in check.length("col") : 'gpar' element 'col' must not be length 0

I'm guessing this means that the default "col" parameter is missing from the layer and the key_glyph parameter throws an error. Is there a way to add default parameters to the layer?

Thanks

mjskay commented 2 years ago

Hmmm this is because of how {ggdist} handles override aesthetics (like slab_color for color) internally. The alpha and linetype aesthetics are not being set for the key unless they are set explicitly, so that ggdist keys for composite geometries (like halfeye) can detect which sub-geometries actually have aesthetics set for them. The ggdist key functions know how to retrieve the default values of these aesthetics from the geometry, but the base ggplot2 key functions don't.

A workaround is to specify them manually; e.g.:

mtcars %>% 
    ggplot(aes(x = mpg, y = as.factor(cyl))) +
    stat_slab(aes(fill = as.factor(cyl)), alpha = 1, linetype = "solid", key_glyph = "timeseries")

image

I'll leave this open to see if I can find a better way to detect usage of aesthetics on sub-geometries that plays more nicely with base ggplot2 key functions.

Ari04T commented 2 years ago

Alright, that makes sense. In that case, it becomes necessary to create a second geom/stat in order to play with for example the alpha value right? Something like this:

mtcars %>% 
    mutate(cyl = as.factor(cyl)) %>% 
    ggplot(aes(x = mpg, y = cyl)) +
    stat_slab(aes(color = cyl, slab_fill = after_scale(alpha(color, 0.5)))) +
    stat_slab(aes(fill = cyl), alpha = 0, linetype = "solid", key_glyph = "timeseries") +
    guides(
        color = "none",
        fill = guide_legend(override.aes = list(alpha = 1)),
        slab_fill = "none"
    )

mjskay commented 2 years ago

Yeah I can't think of another way to manipulate the alpha of the fill separately from the outline in this case.