ggplot2
ggplot2 copied to clipboard
POC: Position guides have acces to layer data
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