I have a function which takes an NSE argument.
Let's say I have a tibble with a column that needs ordering. I want to create a function that can order the name of the column based on the name inputted in the function argument.
However I want it to not order the column if I don't use the argument, hence I use column_name = NULL
as a default argument (or column_name = NA
)
sort_tibble <- function(column_name = NULL) {
tibble_data <- tibble::tibble(NSE_name = c(0.2, -0.4, 1.7, 0.09, -0.6, -1))
if (!is.null(({{ column_name }}))) {
tibble_data <- tibble_data %>% arrange({{ column_name }})
# Do stuff
}
}
sort_tibble(NSE_name)
#> Error in sort_tibble(NSE_name): objet 'NSE_name' not found
Created on 2022-04-11 by the reprex package (v2.0.1)
However despite how many combinations of quote, {{var}} or rlang::eval_tidy, I can't find an idea to make R understand that column_name is not empty (thus used). It can't find it because it's not a variable but a tidy evaluation, except it's not used in a tidy function.
I finally found a solution !
The idea here is not to directly try to inject the data for dplyr using {{var}} but to first use a string as function argument input, and to allow it to be evaluated through dplyr using sym()
and !!
. This allows other non tidy operations to work in the function, including subsetting a data frame or just evaluating whether or not the argument is empty or not (which is my condition for my if function).
I referred to https://tidyeval.tidyverse.org/sec-why-how.html#unquoting-code
Using sym()
turns the string into a symbol.
Symbols are required to be evaluated as a column in dplyr
sym("NSE_name")
# NSE_name
Then use !!
to inject the evaluation into the code
library(tidyverse)
f1 <- function(order = NULL) {
df <-
tibble::tibble(NSE_name = c(0.2, -0.4, 1.7, 0.09, -0.6, -1))
f2(order = order)
}
f2 <- function(order = NULL) {
if (!is.null(order)) {
ordered_df <- df %>% arrange(!!sym(order))
return(ordered_df)
}
else print ("No order")
}
f1(order = "NSE_name")
f1()