tidyverse / ggplot2

An implementation of the Grammar of Graphics in R
https://ggplot2.tidyverse.org
Other
6.46k stars 2.02k forks source link

Width argument to geom_errorbar not passed on when using stat_summary_bin #4647

Closed hummuscience closed 1 week ago

hummuscience commented 2 years ago

When using stat_summary_bin and geom = "errorbar" the width argument used to set the width of the errorbars in geom_errorbar does not work.

The below code produces the same plots with different setting for width

Related to follwing StackOverflow issue: https://stackoverflow.com/questions/42418746/how-to-adjust-width-of-errorbar-created-with-stat-summary-bin

library(tidyverse)

iris %>%
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  stat_summary_bin(geom = "errorbar")
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`

iris %>%
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  stat_summary_bin(geom = "errorbar", width = 0.1)
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`

iris %>%
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  stat_summary_bin(geom = "errorbar", width = 2)
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`

Created on 2021-10-20 by the reprex package (v2.0.1)

thomasp85 commented 2 years ago

Yeah, this is an unfortunate consequence when stats and geoms share an aesthetic or parameter name. Fixing this will be surprisingly difficult I'm afraid

hummuscience commented 2 years ago

Is it because width can be used to set binwidth in stat_summary_bin? Or does width affect something else?

thomasp85 commented 2 years ago

hum... that was my thinking writing this, but now I'm not so sure 😬

I'll have to dig in a bit more when I sit down to fix the issue

hummuscience commented 2 years ago

If it is any help, I could try to dig for the reason. I don't think that I am at the level of actually writing a fix, but maybe I could find out what is causing it...

thomasp85 commented 2 years ago

That is very welcome 🙏

thomasp85 commented 2 years ago

Ah, I can see where things run into each other. stat_summary_bin does not take a width paramater or aesthetic, but it does calculate one based on the given bins/binwidth argument (or its default). Since that is now present in the data given to geom_errorbar it takes precedence over the provided width parameter...

So, my initial hunch was correct, it was just a bit more complicated. I'm afraid we don't have a great solution for this at the moment. I'll keep this issue open to remind us to think about it

teunbrand commented 5 months ago

You can use after_stat() to work around this limitation.

library(ggplot2)

iris |>
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  stat_summary_bin(
    aes(width = after_stat(1)),
    geom = "errorbar"
  )
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`
#> No summary function supplied, defaulting to `mean_se()`

Created on 2024-03-28 with reprex v2.1.0

teunbrand commented 5 months ago

Should a parameter width override the width column in the data? For basically any other aesthetic given as a parameter, say colour = "red", we override any colour variable passed through aes() or computed by the stat.

teunbrand commented 2 months ago

It is also a bit verbose the throw the warning about the summary function 3 times