"Correct" Way to Specifiy Optional Arguments in R Functions

Correct way to specifiy optional arguments in R functions

You could also use missing() to test whether or not the argument y was supplied:

fooBar <- function(x,y){
if(missing(y)) {
x
} else {
x + y
}
}

fooBar(3,1.5)
# [1] 4.5
fooBar(3)
# [1] 3

Optional parameters in R function

You should not trust on NA when argument is expected to get value as data.frame, list etc. is.na returns NA check for each element to those data structures. The better option could be to initialize your argument with NULL and check with is.NULL. Another option could be to use missing function on dfInput argument. Your function definition can be written as:

occInput <- function(fileInput, dfInput = NULL) {  
if (is.NULL(dfInput)) occ.dat <- read.csv(file = fileInput)
else occ.dat <- dfInput

#manipulate the data in occ.dat
}

#OR you can just use missing function

occInput <- function(fileInput, dfInput) {
#Perform missing check
if (missing(dfInput)) occ.dat <- read.csv(file = fileInput)
else occ.dat <- dfInput

#manipulate the data in occ.dat
}

Passing in optional arguments to function in r

You can use the ... argument (documented in ?dots) to pass down arguments from a calling function. In your case, try this:

library(gbm)
library(ggplot2)
data('diamonds', package = 'ggplot2')

example_function <- function(n.trees = 5, ...){
gbm(formula = price~ ., n.trees = 5, data = diamonds, ...)
}


# Pass in the additional 'shrinkage' argument
example_function(n.trees = 5, shrinkage = 0.02)
## Distribution not specified, assuming gaussian
## gbm(formula = price ~ ., data = diamonds, n.trees = 5, shrinkage = 0.02)
## A gradient boosted model with gaussian loss function.
## 5 iterations were performed.
There were 9 predictors of which 2 had non-zero influence.

Passing in list of optional arguments in R

I think the most straightforward way to handle this kind of pattern is to give the function an extra_args parameter that accepts an arbitrary list (and defaults to an empty list if you want to ignore it):

foo <- function(data, extra_args = list(), func = mean, 
cross_depth = NULL, data_table = FALSE) {
# Do stuff
}

Which allows:

varx <- list("var1", "var2", "var3")

foo(data, varx, func = func, data_table = TRUE, cross_depth = 3)

Passing optional arguments with `...` to multiple functions; control argument matching?

1) Define do.call2 which is like do.call except that it accepts unnamed arguments as well as named argument in the character vector accepted which defaults to the formals in the function.

Note that the arguments of mean do not include na.rm -- it is slurped up by the dot dot dot argument -- but the mean.default method does. Also primitive functions do not have formals so the accepted argument must be specified explicitly for those rather than defaulted.

do.call2 <- function(what, args, accepted = formalArgs(what)) {
ok <- names(args) %in% c("", accepted)
do.call(what, args[ok])
}

# test

dat <- c(NA, 1:5)
meanLog <- function(x, ...){
y <- do.call2("log", list(x, ...), "base")
z <- do.call2("mean.default", list(y, ...))
return(z)
}

meanLog(dat, na.rm = TRUE, base = 2)
## [1] 1.381378

# check

mean(log(dat, base = 2), na.rm = TRUE)
## [1] 1.381378

2) Another possibility is to provide separate arguments for mean and log.

(A variation of that is to use dot dot dot for one of the functions and argument lists for the others. For example nls in R uses dot dot dot but also uses a control argument to specify other arguments.)

# test

dat <- c(NA, 1:5)
meanLog <- function(x, logArgs = list(), meanArgs = list()) {
y <- do.call("log", c(list(x), logArgs))
z <- do.call("mean", c(list(y), meanArgs))
return(z)
}

meanLog(dat, logArgs = list(base = 2), meanArgs = list(na.rm = TRUE))
## [1] 1.381378

# check

mean(log(dat, base = 2), na.rm = TRUE)
## [1] 1.381378

How To Pass An Optional Parameter Inside a function of ggplot

First case: ybreak = NULL

is.na(NULL)

Returns:

logical(0)

And therefore (because logical(0) is nothing):

is.na(NULL) == FALSE

Returns:

logical(0)

But if we use is.null (NULL is nothing) instead of is.na (NA is something (just not a number)) :

is.null(NULL)

Returns:

[1] TRUE

and then:

is.null(NULL) == FALSE
[1] FALSE

Second case: ybreak = seq(70, 500, by = 50)

is.na(seq(70, 500, by = 50))
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
if (is.na(seq(70, 500, by = 50)) == FALSE) print("something")
[1] "something"
Warning message:
In if (is.na(seq(70, 500, by = 50)) == FALSE) print("something") :
the condition has length > 1 and only the first element will be used

But we can use all to check multiple booleans at once:

if (all(is.na(seq(70, 500, by = 50)) == FALSE)) print("something")
l[1] "something"

R: write function with optional arguments

You can do:

myfunction <- function(space, start_date, end_date, ..., optionalArgument4 = NULL){

args <- c(...)

filters <- paste(unlist(lapply(seq_along(args),
function(i) sprintf("SMALL_filter%s:{$sf%s:'%s'}",
i, i, args[i]))),
collapse = ",")

api_request <- paste0("https://myapi.com/getData?hello",

#NEEDED
"&space={s:'", space,"'}",
"&period={M:{start:'",start_date,"',end:'",end_date,"'}}",

#OPTIONAL
ifelse(filters=="","",sprintf("&filter={%s}",filters)),

ifelse(!is.null(optionalArgument4),
paste0("&segment=",optionalArgument4),"")

)

return(api_request)
}

You will have to name optionalArgument4 when calling the function:

space <- "earth"
start_date <- "2018-10"
end_date <- "2018-11"
optionalArgument1 <- "America"
optionalArgument2 <- "people"
optionalArgument3 <- "size"
optionalArgument4 <- "ocean"

myfunction(space, start_date, end_date, optionalArgument1, optionalArgument4 = optionalArgument4)
# [1] "https://myapi.com/getData?hello&space={s:'earth'}&period={M:{start:'2018-10',end:'2018-11'}}&filter={SMALL_filter1:{$sf1:'America'}}&segment=ocean"

Using optional arguments in R function

My suggestion

I think the | 10 part is causing the issue, and since when logbase is 10, you get the same whether test evaluates to TRUE or FALSE, you can just remove it. I know you said in a comment this isn't working as expected, but it seems to for me - if it`s still not for you, feel free to comment.

fn1 <- function(x, logbase = NULL){
logbase <- ifelse(test = is.null(logbase), yes = 10, no = logbase)
out <- log(x = x, base = logbase)
return(out)
}

fn1(x = 10, logbase = NULL) # 1
fn1(x = 10, logbase = 2) # 3.321928
fn1(x = 10, logbase = exp(1)) # 2.302585

What the issue with your code was

The issue is anything with | 10 will always evaluate to TRUE. This is because the | operator will convert the arguments on both sides to logical, so something like is.null(2) | 10 is equivalent to as.logical(is.null(2)) | as.logical(10) which evaluates to F | T which is T.

To be clear, | 10 is not related to logbase. What you were looking for is presumably | logbase == 10. This is fine, except when logbase is NULL, you run into issues because NULL == 10 doesn't evaluate to T or F (it's logical(0)).

You can fix this by using ||, rather than |, which would only evaluate logbase == 10 if is.null(logbase) is FALSE, because if the first half of a || is TRUE, then it simply returns TRUE without evaluating the second half.



Related Topics



Leave a reply



Submit