Search code examples
rmetaprogrammingtidyeval

NSE error handling: check for `NA` with NSE/tidy eval


I am writing a function using tidyeval, and I ran into a problem while trying to check for NAs.

I am writing a function to make plots using ggplot2 that looks something like:

my_func <- function(data, x = NA, y = NA) {
  if(is.na(x) & is.na(y)) {
    stop("`x` and `y` cannot both be NA.")
  }
  if(is.na(y)) {
    data %>%
      ggplot2::ggplot(ggplot2::aes(x = {{ x }})) + 
      ggplot2::geom_bar()
  } else {
    data %>%
      ggplot2::ggplot(ggplot2::aes(y = {{ y }})) + 
      ggplot2::geom_bar()
  }
}

The error is:

data("iris")
my_func(data = iris, x = Species)

#> Error in my_func(data = iris, x = Species) :
#>   object 'Species' not found

I've been learning about NSE and metaprogramming from Advanced R, but I am still relatively new to this topic.

I have tried this general function using NAs and is.na and NULLs and is.null. I know that I am missing something with regards to NSE.


Solution

  • We could use missing to create condition

    my_func <- function(data, x, y) {
      
      if(missing(y)) {
        data %>%
          ggplot2::ggplot(ggplot2::aes(x = {{ x }})) + 
          ggplot2::geom_bar()
      } else {
        data %>%
          ggplot2::ggplot(ggplot2::aes(y = {{ y }})) + 
          ggplot2::geom_bar()
      }
    }
    

    -testing

    > my_func(iris, x = Sepal.Length)
    > my_func(iris, y = Sepal.Width)