I have the following function which works:
library(cowplot)
library(tidyverse)
hist_fun <- function(data, ...) {
g <- map(
list(data %>%
select(...) %>%
map2(., names(.),
~{ggplot(data.frame(var = .x), aes(var)) +
geom_histogram(aes(y = after_stat(density))) +
labs(x = .y)
})),
~cowplot::plot_grid(plotlist = .x, ncol = 1))
g
}
#works
hist_fun(mtcars, mpg, cyl, disp)
However, I would like to be able to pass it geom_histogram
arguments too so something like:
hist_fun(mtcars, mpg, cyl, disp, bins = 20, color = "white")
I'm not sure of the best way to approach this. Should I collect everything in the ellipsis in a list and then try to separate out the list into a) variables and b) geom_histogram
arguments, something like:
hist_fun <- function(data, ...) {
everything <- list(...)
#unlist and extract variables/geom_histogram arguments?
#just_vars
#just_geom_histogram
g <- map(
list(data %>%
select(just_vars) %>%
map2(., names(.),
~{ggplot(data.frame(var = .x), aes(var)) +
geom_histogram(aes(y = after_stat(density)), just_geom_histogram) +
labs(x = .y)
})),
~cowplot::plot_grid(plotlist = .x, ncol = 1))
g
}
That seems a bit messy so would it better to separate the variables at the start and keep geom_histogram
arguments to the ellipsis, something like:
hist_fun(mtcars, just_vars = list(), ...)
Any suggestions and the best way to achieve it, particularly when I want to keep the variables unquoted?
Thanks
There are only a small number of arguments that a user might pass to geom_histogram
, so I would just explicitly name these in the function definition. Ensure they go after the ellipsis though.
library(cowplot)
library(tidyverse)
hist_fun <- function(data, ..., color = NA, bins = 30) {
g <- map(
list(data %>%
select(...) %>%
map2(., names(.),
~{ggplot(data.frame(var = .x), aes(var)) +
geom_histogram(aes(y = after_stat(density)),
bins = bins, color = color) +
labs(x = .y)
})),
~cowplot::plot_grid(plotlist = .x, ncol = 1))
g
}
Allowing
hist_fun(mtcars, mpg, cyl, disp, bins = 10, color = "red")
If you didn't want to limit the user to the named arguments you decided upon, you could indeed do it by sorting through the ellipsis arguments, but it's a bit more complex:
hist_fun <- function(data, ...) {
args <- as.list(match.call())[-c(1:2)]
named_args <- args[which(nzchar(names(args)))]
unnamed_args <- args[which(!nzchar(names(args)))]
hist_args <- c(list(mapping = aes(y = after_stat(density))), named_args)
select_args <- c(list(quote(data)), unnamed_args)
g <- map(
list(
map2(do.call('select', select_args),
names(do.call('select', select_args)),
~{ggplot(data.frame(var = .x), aes(var)) +
do.call('geom_histogram', hist_args) +
labs(x = .y)
})),
~cowplot::plot_grid(plotlist = .x, ncol = 1))
g
}
For example
hist_fun(mtcars, mpg, cyl, disp, bins = 15, fill = 'red')