I am making several plots, which for flexibility I am planning to wrap in functions, and as part of that I would like to specify faceting for those plots according to some condition.
Specifically, I have a list of grouping_vars
(per-specified elsewhere) that I use to perform several other manipulations on the data. I'd like to have my plotting functions be able to automatically use a facet_wrap
if there's only one grouping_var
, or if there are two or more variables specified in grouping_var
, use the first two for facet_grid
.
So for instance, if the basic plot is something like
mtcars %>% ggplot() + geom_point(aes(x = hp, y = mpg))
If I specify grouping_vars <- c("cyl")
, I'd like to get, in effect,
mtcars %>% ggplot() +
geom_point(aes(x = hp, y = mpg)) +
facet_wrap(~cyl)
Whereas if I specify grouping_vars <- c("cyl", "carb")
I'd like to get
mtcars %>% ggplot() +
geom_point(aes(x = hp, y = mpg)) +
facet_grid(vars(cyl), vars(carb))
Based on some other answers I've tried doing this:
mtcars %>% ggplot() +
geom_point(aes(x = hp, y = mpg)) +
{if(length(grouping_vars==1)) facet_wrap(grouping_vars[[1]])} +
{if(length(grouping_vars>=2)) facet_grid(vars(grouping_vars[[1]]), vars(grouping_vars[[2]]))}
but it doesn't seem to work. Among other things, if there's only one element in grouping_vars
, it gives me Error in grouping_vars[[2]] : subscript out of bounds
.
Is there a way to conditionally specify faceting like this?
Following the advice in the vignette here, we should be able to use vars()
with the .data
pronoun as follows:
library(ggplot2)
plot_mtcars <- function(grouping_vars = NULL) {
p <- ggplot(mtcars) +
geom_point(aes(x = hp, y = mpg))
if (length(grouping_vars) == 1) {
p <- p + facet_wrap(vars(.data[[grouping_vars]]))
} else if (length(grouping_vars) == 2) {
p <- p + facet_grid(vars(.data[[grouping_vars[1]]]),
vars(.data[[grouping_vars[2]]]))
}
p
}
plot_mtcars("cyl")
plot_mtcars(c("cyl", "vs"))
Created on 2023-03-14 by the reprex package (v2.0.0)