To build a function factory, begin by writing the function that you want to generalize (like a normal function). Here we’ll generalize a function to add a color scale to a ggplot using a custom palette.
my_scale_color <- function(discrete = TRUE, reverse = FALSE, ...) {
my_palette <- c(
"#772277", "#333388", "#1144aa", "#55aa11",
"#f40000", "#f47a00", "#ffe314"
)
if (reverse) {
my_palette <- rev(my_palette)
}
pal <- colorRampPalette(my_palette, ...)
if (discrete) {
ggplot2::discrete_scale(
aesthetics = "colour",
scale_name = "my_color_scale",
palette = pal,
...
)
} else {
ggplot2::scale_color_gradientn(colors = pal(256),)
}
}
ggplot2::ggplot(mtcars) +
ggplot2::aes(x = mpg, y = cyl, color = factor(gear)) +
ggplot2::geom_point() +
my_scale_color()
#> Warning: The `scale_name` argument of `discrete_scale()` is deprecated as of ggplot2
#> 3.5.0.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
We could conceivably want to generalize this function to create a similar function, given a palette and (optionally) the name of the scale.
my_scale_color_generic <- function(discrete = TRUE, reverse = FALSE, ...) {
my_palette <- this_palette
if (reverse) {
my_palette <- rev(my_palette)
}
pal <- colorRampPalette(my_palette, ...)
if (discrete) {
ggplot2::discrete_scale(
aesthetics = "colour",
scale_name = this_scale_name,
palette = pal,
...
)
} else {
ggplot2::scale_color_gradientn(colors = pal(256),)
}
}
We can use factory::build_factory
to turn that function
into a factory.
my_scale_color_factory <- build_factory(
fun = my_scale_color_generic,
this_palette,
this_scale_name = "my_color_scale"
)
Using our factory with the values we started with should reproduce the original function.
my_scale_color_factory(
this_palette = c(
"#772277", "#333388", "#1144aa", "#55aa11",
"#f40000", "#f47a00", "#ffe314"
)
)
#> function (discrete = TRUE, reverse = FALSE, ...)
#> {
#> my_palette <- c("#772277", "#333388", "#1144aa", "#55aa11",
#> "#f40000", "#f47a00", "#ffe314")
#> if (reverse) {
#> my_palette <- rev(my_palette)
#> }
#> pal <- colorRampPalette(my_palette, ...)
#> if (discrete) {
#> ggplot2::discrete_scale(aesthetics = "colour", scale_name = "my_color_scale",
#> palette = pal, ...)
#> }
#> else {
#> ggplot2::scale_color_gradientn(colors = pal(256), )
#> }
#> }
Note: If you use factory
to build a factory in a
package, we recommend that you copy/paste the resulting function
definition into your package, rather than using the
factory::build_factory
call directly in your package. This
will allow you to better comment your code, and will avoid build
errors.