tidyverse / ggplot2

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

Binned scales don't work with `limits = function()` #6144

Open arcresu opened 6 days ago

arcresu commented 6 days ago

According to the docs, scale_x_binned() and friends can be given a function for limits. However, this fails when a transform is also set.

This example is supposed to make a bar plot counting days in each month (i.e. a binned date scale), and works fine until a limits function is provided:

library(ggplot2)

df <- data.frame(x = seq(as.Date("2024-01-01"), as.Date("2024-06-30"), "day"))

ggplot(df) +
  geom_bar(aes(x)) +
  scale_x_binned(
    breaks = scales::breaks_width("1 month"),
    transform = scales::transform_date(),
    # works if the following line is commented out
    limits = function(x) { x }
  )

# Error in `scale_x_binned()`:
# ! Binned scales only support continuous data.

Looking through the code, it seems that ScaleBinned itself is fine (all access goes through ScaleBinned$get_limits() which handles function values properly), but the binned_scale() constructor causes the error here:

https://github.com/tidyverse/ggplot2/blob/ddd207e926cc1c1847dc661d9a099b8ec19c4010/R/scale-.R#L321-L324

In that snippet, limits is the bare value passed in by the user, so if that's a function then it's forwarded as-is to the transform. The date transform says that a function object is not numeric hence the error.

Found on 3.5.1 but the relevant code is the same on main.

teunbrand commented 6 days ago

Thanks for the report! I can confirm this is indeed a bug, though I'm getting a slightly different error message.