I would like to develop a simple function that would enable me to save graphs of specific characteristics. For example, I'm running some analysis producing a set of histograms:
# Data and Libs
data(mtcars); require(ggplot2)
# Graphs
## A
grph_a <- ggplot(data = mtcars) +
geom_histogram(aes(mpg)) +
ggtitle("MPG")
## B
grph_b <- ggplot(data = mtcars) +
geom_histogram(aes(cyl)) +
ggtitle("CYL")
Instead of writing ggsave
command for each of those graphs I would like to do it via function. It makes sense as I will be repeating the same steps for a number of graphs across various similar projects. I would like for the function to do one thing:
ggsave
with a set parameters and save them to provide path.Ideally, I would like for the function call to look like that
ExportGraphs(graphNamePhrase = "grph_", filesPath = "Somewhere/GaphsAndStuff/)
I don't want to be specifying more stuff.
My function looks like that:
ExportGraphs <- function(graphNamePhrase = "grph_",
filesPath, objects = ls()) {
# Check if required packages are available
req_pkgs <- c("ggplot2","grid")
## Check if the package is loaded and load if needed
for (i in 1:length(req_pkgs)) {
pkg <- req_pkgs[i]
if (length(grep(pkg, search())) == 0) {
lapply(pkg, require, character.only = TRUE)
}
}
# Create list of objects
save_grphs <- grep(pattern = graphNamePhrase, x = objects,
ignore.case = TRUE, value = TRUE)
# Create save loop
for (i in 1:length(save_grphs)) {
# Create file path
fle_path <- paste0(filesPath, save_grphs[i], ".png")
# Save file
ggsave(filename = fle_path, plot = save_grphs[i],
width = 7, height = 7, units = 'cm', scale = 2, dpi = 600)
}
}
Obviously, the code:
save_grphs <- grep(pattern = graphNamePhrase, x = objects,
ignore.case = TRUE, value = TRUE)
won't work as what is passed via the objects = ls()
will be a string. My question is how can I get around it. Is there a way to use get
on the parent frame from which the function is called? Not the easiest solution but I could search objects via string. Or can I run ls
with grep
in the function call and pass all matching objects?
I tried the solution with mget
:
ExportGraphs <- function(graphNamePhrase = "grph_",
filesPath, objects = ls()) {
# Check if required packages are available
req_pkgs <- c("ggplot2","grid")
## Check if the package is loaded and load if needed
for (i in 1:length(req_pkgs)) {
pkg <- req_pkgs[i]
if (length(grep(pkg, search())) == 0) {
lapply(pkg, require, character.only = TRUE)
}
}
# Create list of objects
save_grphs <- grep(pattern = graphNamePhrase, x = objects,
ignore.case = TRUE, value = TRUE)
save_grphs <- mget(objects[save_grphs])
# Create save loop
for (i in 1:length(save_grphs)) {
# Create file path
fle_path <- paste0(filesPath, save_grphs[i], ".png")
# Save file
ggsave(filename = fle_path, plot = save_grphs[[i]],
width = 7, height = 7, units = 'cm', scale = 2, dpi = 600)
}
}
But it seems that I would have to adjust the loop as subscription appears to be out of bounds:
Error in save_grphs[[i]] : subscript out of bounds Called from: inherits(plot, "ggplot")
This works for me. There are many places to further optimize the function:
ExportGraphs <- function(graphNamePhrase = "grph_",
filesPath, objects = ls()) {
# Check if required packages are available
req_pkgs <- c("ggplot2","grid")
## Check if the package is loaded and load if needed
for (i in 1:length(req_pkgs)) {
pkg <- req_pkgs[i]
if (length(grep(pkg, search())) == 0) {
lapply(pkg, require, character.only = TRUE)
}
}
# Create list of objects
index <- grep(pattern = graphNamePhrase, x = objects,
ignore.case = TRUE)
save_grphs <- mget(objects[index])
# Create save loop
for (i in 1:length(save_grphs)) {
# Create file path
fle_path <- paste0(filesPath, objects[index][i], ".png")
# Save file
ggsave(filename = fle_path, plot = save_grphs[[i]],
width = 7, height = 7, units = 'cm', scale = 2, dpi = 600)
}
}