Background
I am writing a ggplot2 extension and wish to make use of ggplot_add()
with a custom method so that I can influence behavior down the ggplot chain while referencing information from up the ggplot chain, such as attributes and layer position.
I chose to use ggplot_add()
because I wanted to influence how labels appear in the legend of the ggplot output using guides()
in combination with override.aes
.
Reprex
Below is a reprex with a geom function to establish the structure
, a custom ggplot_add()
method to create the layer and influence behavior, and a custom Geom
built almost completely after GeomLabel
.
Note I am not supplying
custom_legend_fixing_function()
, as it is just a placeholder example.
library(ggplot2)
geom_new_label <- function(mapping = NULL, data = NULL,
stat = "identity", position = "identity",
...,
parse = FALSE,
label.padding = unit(0.25, "lines"),
label.r = unit(0.15, "lines"),
label.size = 0.25,
size.unit = "mm",
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
structure(
"geom_new_label",
class = c("new_label", "ggnew_layer"),
stat = stat,
position = position,
mapping = mapping,
data = data,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
parse = parse,
label.padding = label.padding,
label.r = label.r,
label.size = label.size,
size.unit = size.unit,
... = ...
)
)
}
ggplot_add.new_label <- function(object, plot, object_name) {
new_layer <- layer(
data = attr(object, "data"),
mapping = attr(object, "mapping"),
stat = attr(object, "stat"),
geom = GeomNewLabel,
position = attr(object, "position"),
key_glyph = "label",
show.legend = attr(object, "show.legend"),
inherit.aes = attr(object, "inherit.aes"),
params = attr(object, "params")
)
plot$layers <- append(plot$layers, new_layer)
# Fix legend ----
# Impetus for using ggplot_add(), function logic not shown
label_override <- custom_legend_fixing_function(plot, new_layer)
plot <- plot +
guides(
colour = guide_legend(
override.aes = list(
label = label_override
)
)
)
plot
}
GeomNewLabel <- ggproto("GeomNewLabel", Geom,
required_aes = c("x", "y", "label"),
default_aes = aes(
colour = NA, fill = NA, size = 3.88, angle = 0,
hjust = 0.5, vjust = 0.5, alpha = NA, family = "", fontface = 1,
lineheight = 1.2
),
draw_panel = function(data, panel_params, coord, parse = FALSE,
na.rm = FALSE,
label.padding = unit(0.25, "lines"),
label.r = unit(0.15, "lines"),
label.size = 0.25,
size.unit = "mm") {
# Return all components
grid::gList(
GeomLabel$draw_panel(data, panel_params, coord,
parse = FALSE,
na.rm = na.rm,
label.padding = label.padding,
label.r = label.r,
label.size = label.size,
size.unit = size.unit
)
)
}
)
Created on 2024-06-12 with reprex v2.1.0
The Problem
For typical warnings, like below, the parent reference points to the original function:
mtcars |>
ggplot() +
geom_label(mapping = aes(x = mpg, y = cyl, label = disp),
test = "test")
Warning message:
In geom_label(mapping = aes(x = mpg, y = cyl, label = disp), test = "test") :
Ignoring unknown parameters: `test`
However, with my use of ggplot_add()
it references ggplot_add()
:
Warning message:
In ggplot_add(object, p, objectname) :
Ignoring unknown parameters: `test`
I realize this is expected, and because the call to layer()
occurs inside of ggplot_add()
, but I’m wondering if there is a way I can restructure my setup so it comes from geom_new_label()
?
Thank you!