rggplot2ggproto

Default breaks in ggplot2 - where are the break limits dropped for legend guides and polar coordinate y axis labels


This is essentially a follow up question on How does ggplot calculate its default breaks? and I came across this when trying to find a slightly more elegant solution for How to add y-axis labels inside coord_polar graph ggplot?.

Apparently, the breaks are always calculated with scales::extended_breaks. However, it seems that the limits of those breaks are dropped with polar coordinates, as well as with a legend guide on continuous data.

Where does this happen?

library(ggplot2)

ggplot(mtcars, aes(x = mpg, y = mpg, size = hp)) +
  geom_point() +
  coord_polar() +
  labs(color = 'am')

Compare with


scales::extended_breaks()(mtcars$mpg)
#> [1] 10 15 20 25 30 35
scales::extended_breaks()(mtcars$hp)
#> [1]  50 100 150 200 250 300 350

Created on 2023-04-01 with reprex v2.0.2


Solution

  • As I mentioned in my comment the issue with both the guides for non-positional scales and coord_polar is that the scale or more exactly the limits don't get expanded. For coord_polar even the default exapnsion is set to zero which happens in CoordPolar$setup_panel_params:

    ...
    if (self$theta == n) {
      expansion <- ggplot2:::default_expansion(scale, c(0, 0.5), c(0, 0))
    } else {
      expansion <- ggplot2:::default_expansion(scale, c(0, 0),   c(0, 0))
    }
    ...
    

    As a consequence the lower and upper breaks returned by scales::breaks_extended will in general get dropped as it does not fall inside the limits.

    This said, one option would be to extend the limits or to use a custom function which does this by computing the limits as range(scales::breaks_extended()):

    library(ggplot2)
    
    limits_extended <- function() {
      function(x) {
        range((scales::breaks_extended())(x))
      }
    }
    
    ggplot(mtcars, aes(x = mpg, y = mpg, size = hp)) +
      geom_point() +
      scale_x_continuous(limits = limits_extended()) +
      scale_y_continuous(limits = limits_extended()) +
      scale_size(limits = limits_extended()) +
      coord_polar() +
      labs(color = 'am')