Idea
tjmahr posted a neat hack to embed auto-embed the text used to create a ggplot as the title of the plot itself.
I wondered if you could somehow extract the ggplot call text from a ggplot object itself.
Proof-of-concept: Reverse engineering a ggplot call
library(ggplot2)
library(dplyr)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# reverse_mapping -> "aes(x = ..., y = ...)"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_mapping <- function(mapping) {
aes_args <- paste(names(mapping), stringr::str_sub(as.character(mapping), start=2), sep = "=", collapse = ", ")
aes_text <- glue::glue("aes({aes_args})")
aes_text
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# reverse aesthetic params -> "size = 3"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_aes_params <- function(aes_params) {
if (length(aes_params) == 0) {
NULL
} else {
paste(names(aes_params), unname(aes_params), sep = "=", collapse = ", ")
}
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# reverse_layer -> "geom_point(aes(mpg, wt), size = 3)"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_layer <- function(layer) {
geom_name <- ggplot2:::snakeize(class(layer$geom)[1])
aes_text <- reverse_mapping(layer$mapping)
aes_params_text <- reverse_aes_params(layer$aes_params)
geom_args <- paste(c(aes_text, aes_params_text), collapse = ", ")
glue::glue("{geom_name}({geom_args})")
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Reverse plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_plot <- function(p) {
layers <- p$layers %>% map_chr(reverse_layer)
plot_text <- paste(c("ggplot(data)", layers), collapse = "+\n")
styler::style_text(plot_text)
}
Example
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a plot object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(p <- ggplot(mtcars) +
geom_point(aes(mpg, wt), size = 3) +
geom_line(aes(mpg, wt)))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Determine the ggplot call from the ggplot object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_plot(p)
Warning: Could not use colored = TRUE, as the package prettycode is not
installed. Please install it if you want to see colored output or see `?
print.vertical` for more information.
ggplot(data) +
geom_point(aes(x = mpg, y = wt), size = 3) +
geom_line(aes(x = mpg, y = wt))