TL;DR Two functions in ggplot2 are overwritten (ggplot and +) to achieve code transparency and reproducibility when ggplot2 is used inside a function.
It is believed that merging ggcall-like into ggplot2 can significantly enhance its functionality and accessibility, benefiting the entire R community.
Powered by metaprogramming.
Updated 2025-01-07
Overview
Transparency and reproducibility are fundamental principles in data analysis across various fields, from academic research to industry applications. The ggcall
package enhances the functionality of ggplot2
by enabling users to retrieve the complete code used to generate a ggplot
object inside a function. This package is beneficial for understanding and replicating complex ggplot2
plots returned by a function. From technical point of view, ggcall
extends ggplot2
+
operator and ggplot
function to track the history of plot construction.
ggcall
makes a developer’s life easier and limits the need to use base r metaprogramming or rlang
.
patchwork
ggplot2 related operators like +
, -
, *
, |
, &
and /
are optionally supported. patchwork
is a package that expands the API to allow for arbitrarily complex composition of plots by, among others, providing mathematical operators for combining multiple plots.
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. Please access such templates here.
Implementation in Your Own Package
The ggcall can be implemented as a standalone solution.
A “standalone” file implements a minimum set of functionality in such a way that it can be copied into another package. usethis::use_standalone()
makes it easy to get such a file into your own repo/package and later update it if needed.
Example of standalone file in another package, rlang
The usethis
>= 2.2.0 is required.
install.packages("usethis")
STANDALONE means copy paste the files and add dependencies to your own package.
Please create an R package if not having such yet.
::create_package() usethis
WITH patchwork
support
# Add ggplot2, patchwork as your package dependencies
# copy paste the ggcall.R file to your own package R directory
# copy paste the patchwork.R file to your own package R directory
::use_standalone("polkas/ggcall", "patchwork.R", ref = "v0.3.4")
usethis# you may need to update the files time to time with usethis::use_standalone
WITHOUT patchwork
support
# Add ggplot2as your package dependencies
# copy paste the ggcall.R file to your own package R directory
::use_standalone("polkas/ggcall", "ggcall.R", ref = "v0.3.4")
usethis# you may need to update the files time to time with usethis::use_standalone
GENERAL COMMENTS:
# Apply only if needed
# In your own code remove all ggplot2:: prefix-ing before ggplot function calls
# ggplot2::ggplot(...) -> ggplot(...)
# DO NOT import ggplot function from ggplot2
#' @rawNamespace import(ggplot2, except = c(ggplot))
# Combine ggcall +.gg operator with your own one if you already overwrited it in your package
# e.g. GGally package requires such step
# Consider moving the ggplot2 from DESCRIPTION Imports to Depends
# if your users will benefit from extending results with further layers
Example
The ggcall_example repository contains a simple implementation of ggcall. forest_plot
and barbell_plot
functions are a part of ggcall.example
package. Typically, it will be a function returning ggplot2
object from your own R package where you implemented ggcall
.
::install_github("https://github.com/Polkas/ggcall_example")
remoteslibrary(ggcall.example)
# Print the body of the function
forest_plot
<- data.frame(
df Treatment = c("Treatment A", "Treatment B", "Treatment C"),
Estimate = c(0.2, 0.5, -0.1),
CI_lower = c(0.1, 0.3, -0.3),
CI_upper = c(0.3, 0.7, 0.1)
)
# Call the function, gg_plot is a ggplot object
<- forest_plot(df, "Estimate", "CI_lower", "CI_upper", "Treatment")
gg_forest
gg_forest
# Retrieve the plot construction code
<- ggcall(gg_forest)
call_forest
# Optionally: Style the code with styler
# install.packages("styler")
::style_text(paste(deparse(call_forest), collapse = "\n"))
styler
# Optionally: add assignments to call
::style_text(paste(deparse(ggcall_add_assignments(call_forest)), collapse = "\n"))
styler
# Optionally: reevaulate the call
eval_ggcall(call_forest)
Why ggcall matters
For developers who build R packages that include functions generating ggplot2
plots, maintaining clarity over how each plot is constructed can be challenging. ggcall
addresses this by enabling:
- Code Tracking: Extends the
+
operator and theggplot
function to maintain a history of plot construction.
- Accessible History: Users can effortlessly access a sequence of
ggplot2
calls used to build plots, enhancing understanding and teaching opportunities.
- Reproducibility: Facilitates the easy replication and modification of plots, which is essential for testing and extending visualizations.
Join the ggcall Community
Visit the GitHub repository to download ggcall
, view detailed documentation, and start making your ggplot2 visualizations more transparent and reproducible today!
Your feedback and contributions are highly appreciated as they help to refine ggcall
to better serve the R community.