The ggcall
package enhances the functionality of ggplot2
by enabling users to retrieve the complete code used to generate a ggplot
object. This package is beneficial for understanding and replicating complex ggplot2
plots, especially when the original code is not accessible, e.g., hidden in the package's internals.
ggcall
is especially useful for R developers who build their own packages comprising functions that generate ggplot2
plots. These functions often involve multiple layers and complex plotting logic. By using ggcall
, developers can make their plotting solutions more transparent and reproducible, thereby enhancing the utility and reliability of their packages. Please note, ggcall
is not intended for packages that create custom geom/stat functions.
An excellent implementation example is to create a bunch of ggplot templates, and we want them to be functions. Then, each template will generate the expected plot, and the ggplot2 code behind is easy to get.
The solution is in the early development and is expected not to work in specific situations like with cowplot or when transition to grobs occurs.
With ggcall
, retrieving the construction calls of a ggplot
object is straightforward:
remotes::install_github("https://github.com/Polkas/ggcall")
library(ggcall)
# Example: Create a function which combines a few ggplot layers
# Typically, it will be a function from your R package where you implemented ggcall
func <- function(data, x, y, bool = TRUE) {
# layers have to be added with +
gg <- ggplot(data, aes(x = .data[[x]], y = .data[[y]])) +
geom_point(alpha = 0.4) +
facet_grid(~gear)
if (bool) {
gg <- gg + theme(axis.title.x = element_blank())
}
func_internal <- function(gg) {
gg + labs(x = "custom xlab")
}
func_internal(gg)
}
# gg_plot is a ggplot object
gg_plot <- func(mtcars, "wt", "mpg")
print(gg_plot)
# Retrieve the plot construction code
plot_call <- ggcall(gg_plot)
plot_call
# Optionally: Style the code with styler
# install.packages("styler")
styler::style_text(backports:::deparse1(plot_call))
# Optionally: add assignments to call
plot_call_with_assignments <- ggcall_add_assignments(plot_call)
styler::style_text(
paste(deparse(plot_call_with_assignments), collapse = "\n")
)
# Optionally: access call environment
# Access call environment and/or use it to evaluate the call
plot_call_env <- ggcall_env(plot_call)
as.list(plot_call_env)
# Optionally: reevaulate the call
# Reproduce the plot by evaluating the code
eval_ggcall(plot_call)
eval_ggcall(plot_call_with_assignments)
# Optionally overwrite variables
eval_ggcall(plot_call, mtcars = mtcars[1:10, ], x = "gear")
- Code Tracking: Extends
ggplot2
+
operator andggplot
function to track the history of plot construction. - Accessible History: Easily access the complete sequence of
ggplot2
calls that were used to build a plot. - Reproducibility: Facilitates the replication and modification of existing
ggplot2
plots.
# Apply only if needed
# Remove all ggplot2:: prefix-ing before ggplot function calls
# ggplot2::ggplot(...) -> ggplot(...)
# copy paste the ggcall.R file to your own package
# you may need to update the file time to time
# ADD ggcall to Depends or Imports section in DESCRIPTION file
# If added to Depends then all ggcall functions will be preloaded when loading your own package
# If added to Imports the end user will have to library(ggcall) to get the ggcall functionalities
# DO NOT import ggplot function from ggplot2 instead import it from ggcall
# a. When importing all ggplot2 functions
# #' @rawNamespace import(ggplot2, except = c(ggplot))
# #' @import ggcall
# b. When importing specific ggplot2 functions
# #' @importFrom ggplot2 geom_line
# #' @importFrom ggcall ggplot
ggcall
was successfully integrated into popular R packages like GGally
. Please take into account that GGally
had already overwritten the + ggplot2
function. Thus, the overwriting practice seems to be popular.
These implementations demonstrate ggcall
’s versatility and its capability to enhance the functionality of existing packages.
check out the inst/ggally.R for more details
remotes::install_github("https://github.com/Polkas/ggally")
library(GGally)
###########################
# Example for GGally ggcorr
###########################
data(mtcars)
gg <- GGally::ggcorr(
mtcars,
name = expression(rho),
geom = "circle",
max_size = 10,
min_size = 2,
size = 3,
hjust = 0.75,
nbreaks = 6,
angle = -45,
palette = "PuOr",
legend.position = "top"
) +
ggtitle("Correlation Matrix for mtcars Dataset")
# gg is a ggplot object
gg
# Retrieve the plot construction code
gg_call <- ggcall(gg)
gg_call
# Optionally: Style the code with styler
styler::style_text(deparse1(gg_call))
# Optionally: add assignments to call
gg_call_with_assignments <- ggcall_add_assignments(gg_call)
gg_call_with_assignments
styler::style_text(
paste(deparse(gg_call_with_assignments), collapse = "\n")
)
# Optionally: reevaulate the call
# Reproduce the plot by evaluating the code
eval_ggcall(gg_call_with_assignments)
eval_ggcall(ggcall_add_assignments(gg_call))
##############################
# Example for GGally ggscatmat
##############################
data(iris)
gg <- GGally::ggscatmat(iris, color = "Species", columns = 1:4)
# gg is a ggplot object
gg
# Retrieve the plot construction code
gg_call <- ggcall(gg)
gg_call
# Optionally: Style the code with styler
styler::style_text(deparse1(gg_call))
# Optionally: add assignments to call
gg_call_with_assignments <- ggcall_add_assignments(gg_call)
gg_call_with_assignments
styler::style_text(
paste(deparse(gg_call_with_assignments), collapse = "\n")
)
# Optionally: reevaulate the call
# Reproduce the plot by evaluating the code
eval_ggcall(gg_call)
eval_ggcall(gg_call_with_assignments)
##########################
# Example for GGally ggduo
##########################
# Not supported for ggmatrix like plots
# ggcall will fail as ggmatrix plots are not build with pure ggplot2
gg <- GGally::ggduo(tips, mapping = ggplot2::aes(colour = sex), columnsX = 3:4, columnsY = 1:2)
ggplot2::is.ggplot(gg)
# Fail gg_call <- ggcall(gg)
Contributions to ggcall
are welcome. Please refer to the contribution guidelines for more information.