I am trying to create a plot function that can plot different colors for a column with factors if .f2=NULL, and an interaction of the .f1 and .f2 columns if the .f2 parameter is not NULL. The if statement already doesn't work when .f2 is not NULL. After that I try to create the interaction call but that doesn't work.
I'm aware I can also create an if statement that creates two seperate aes functions but I was wondering if I could do it like below.
input = tibble(x=1:100,y=rnorm(100),f1=factor(rep(c("c",'d'),each=50)),f2=factor(rep(c("a",'b'),50)))
plot_interaction = function(.df, .x, .y, .f1, .f2=NULL) {
if (!is.null(.f2)) {
.en1 = .f1 |> enexpr() |> as.character()
.en2 = .f2 |> enexpr() |> as.character()
.expr=paste0('interaction(',.en1,',',.en2,')')
.expr = expr(.expr)
} else
.expr = ensym(.f1)
ggplot(.df, aes(x = {{ .x }}, y = {{ .y }}, colour = {{ .expr}})) +
geom_point(size = 4, alpha = 0.5)
}
plot_interaction(input, x, y, f1)
plot_interaction(input,x, y, f1, f2)
You should use missing
rather than is.null
to avoid your specific error.
However, your code won't generate interactions in the event of .f2
being present, because then your conditional will output an expression containing the symbol .expr
rather than a quosure containing the parsed code you wish to inject. One option is to use rlang::parse_quo
rather than expr
:
library(tidyverse)
input <- tibble(x = 1:100, y = rnorm(100),
f1 = factor(rep(c("c", 'd'), each = 50)),
f2 = factor(rep(c("a", 'b'), 50)))
plot_interaction <- function(.df, .x, .y, .f1, .f2) {
if(missing(.f2)) {
.expr <- ensym(.f1)
} else {
.en1 <- .f1 |> enexpr() |> as.character()
.en2 <- .f2 |> enexpr() |> as.character()
.expr <- paste0('interaction(', .en1, ',', .en2, ')')
.expr <- rlang::parse_quo(.expr, env = parent.frame())
}
ggplot(.df, aes(x = {{ .x }}, y = {{ .y }}, colour = {{ .expr}})) +
geom_point(size = 4, alpha = 0.5)
}
This now allows:
plot_interaction(input, x, y, f1)
And
plot_interaction(input,x, y, f1, f2)