Skip to content

scale_x_binned() doesn't work with geom_tile() #5294

Closed as not planned
Closed as not planned
@hughjonesd

Description

@hughjonesd

The following code works, producing output with xmin and xmax aligned to bins:

ggplot(mtcars, aes(mpg, hp)) + 
  geom_rect(aes(xmin = mpg - 5, xmax = mpg + 5, ymin = hp - 5, ymax = hp + 5)) + 
  scale_x_binned(breaks = seq(0,60, 10))

But this code, which ought to do the same thing, produces an empty plot:

ggplot(mtcars, aes(mpg, hp)) + 
  geom_tile(aes(x = mpg, y = hp, height = 10, width = 10)) + 
  scale_x_binned(breaks = seq(0,60, 10))

The underlying reason is in the second call to layout$map_position() in ggplot_build().

  1. There, the binned scale tries to remap x variables back from a factor to (the binned version of) their original values. For GeomRect which has xmax and xmin from the start, this works.
  2. But GeomTile calculates xmin and xmax from x and width. By the time it gets to layer$compute_geom_1, x has been transformed to a "factor"-style numeric of bins. The geom doesn't realise this and happily adds the original width to the bin.
  3. Then the second call to layout$map_position() takes this wonky data and turns it back, typically to NA.
  4. Finally when the geom displays, the NA values for xmin and xmax are removed.

In other words, GeomTile$setup_data() is being called after the first map_position(), but in this case at least, it needs to be called before it.

This bug exists in ggplot2 3.4.2, and also on github main as of today.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions