Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing an optional data frame column to a custom function

Tags:

function

r

nse

I have a custom function that takes as input a data frame and then a selection of columns from that data frame, like this:

library(dplyr)
df <- data.frame(x = c(1, 2, 3, 4, 5), y = c(11, 12, 13, 14, 15))

sample_fun <- function(df, x, y) {
  df <- df %>% 
    mutate(z = {{x}} * {{y}})
  }

df_out <- sample_fun(df, x, y)

I'd like to make one of the data frame columns optional, and then have the function test for its presence using !if.null(). If this was an object, rather than a data frame column, I would do this:

sample_fun <- function(df, x, y = NULL) {
  if(!is.null(y)) {
    df <- df %>% 
      mutate(z = {{x}} * y)
  }
  else(df <- df %>%
         mutate(z = {{x}}))
}

df_out <- sample_fun(df, x) 
df_out2 <- sample_fun(df, x, y)

However, I can't figure out how to check for the presence of the data column. Both if(!is.null(y)) and if(!is.null({{y}})) return Error: object 'y' not found. What is the best way to check for the presence of y, when y is a data frame column rather than an independent object?

like image 847
Jaken Avatar asked Sep 02 '25 14:09

Jaken


2 Answers

One option is to check if the y variable is missing, instead of using NULL as a placeholder.

sample_fun <- function(df, x, y) {
  if (!missing(y)) {
    df <- mutate(df, z = {{x}} * {{y}})
  } else {
    df <- mutate(df, z = {{x}})
  }
  return(df)
}
df_out <- sample_fun(df, x) 
df_out2 <- sample_fun(df, x, y)
like image 161
Axeman Avatar answered Sep 05 '25 04:09

Axeman


The problem with the code in the question is that is.null cannot take an unquoted variable. The code there would work if quo_is_null(enquo(y)) is used in place of is.null(y) . In that case add a library(rlang) as well.

Alternately give y a default value of 1.

library(dplyr)

sample_fun <- function(df, x, y = 1) df %>% mutate(z = {{x}} * {{y}})

sample_fun(df, x, y)
##   x  y  z
## 1 1 11 11
## 2 2 12 24
## 3 3 13 39
## 4 4 14 56
## 5 5 15 75

sample_fun(df, x)
##   x  y z
## 1 1 11 1
## 2 2 12 2
## 3 3 13 3
## 4 4 14 4
## 5 5 15 5
like image 43
G. Grothendieck Avatar answered Sep 05 '25 05:09

G. Grothendieck