Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC: Position guides have acces to layer data #6343

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

teunbrand
Copy link
Collaborator

This PR aims to fix #6247.

Briefly, it adds the plumbing to let panel data reach the get_layer_key() method of position guides.

I've put this in as a draft, because I'm not entirely sure that we should take this approach.
It has some overhead because it needs to split up data by panel, making code slower.
We can illustrate with this benchmark:

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

p <- ggplot(mpg, aes(displ, hwy, colour = drv)) +
  geom_point() +
  facet_grid(year ~ cyl)

bench::mark(ggplotGrob(p), min_iterations = 10)
#> Warning: Some expressions had a GC in every iteration; so filtering is
#> disabled.
#> # A tibble: 1 × 6
#>   expression         min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>    <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ggplotGrob(p)    101ms    105ms      6.51    10.8MB     11.7

Created on 2025-02-21 with reprex v2.1.1

The exact same code on the main branch gives this result:

#> # A tibble: 1 × 6
#>   expression         min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>    <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 ggplotGrob(p)   81.3ms   82.3ms      7.71    10.5MB     12.3

To illustrate that it works, we can assemble a quick-and-dirty guide extension that displays a density line for the data it sees, instead of the actual axis line.

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

GuideDensity <- ggproto(
  "GuideDensity", GuideAxis,
  get_layer_key = function(params, layers, data = NULL, theme = NULL) {
    vals <- unlist(lapply(data, function(d) d[[params$aesthetic]]))
    dens <- density(vals, from = min(vals), to = max(vals))
    params$decor <- data.frame(x = dens$x, z = dens$y / max(dens$y))
    params
  },
  build_decor = function(decor, grobs, elements, params) {
    element_grob(
      elements$line,
      x = unit(decor$x, "npc"),
      y = unit(1 - decor$z, "npc")
    )
  }
)

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  guides(x = new_guide(super = GuideDensity, available_aes = "x")) +
  theme(axis.line = element_line())

Created on 2025-02-21 with reprex v2.1.1

@teunbrand
Copy link
Collaborator Author

In addition, it is not entirely clear what data the guide should recieve in terms of facetting and free scales. For example, in grid facets, an x-axis guide for the first column should perhaps see all the data in that column, but that doesn't quite hold for facet_wrap(). All in all I'm not convinced by the goal here.

@teunbrand teunbrand marked this pull request as draft February 21, 2025 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose position guides to layer data
1 participant