How to Check Existence of an Input Argument for R Functions

How to check existence of an input argument for R functions

@Sacha Epskamp has a pretty good solution, but it doesn't always work. The case where it fails is if the "z" argument is passed in as NULL...

# Sacha's solution
myFun <- function(x, y, ...) {
args <- list(...)
exist <- !is.null(args[['z']])
return(exist)
}

myFun(x=3, z=NULL) # FALSE, but should be TRUE!

# My variant
myFun2 <- function(x, y, ...) {
args <- list(...)
exist <- "z" %in% names(args)
exist
}

myFun2(x=3, z=NULL) # TRUE

How to check if any variable is defined in argument (...) in R?

Does this suffice?

# Define a function for remaining scenarios
f = function(...){"a" %in% names(list(...))}

# Scenario 3
f()
# [1] FALSE

# Scenario 4
a <- 10
f()
# [1] FALSE

# Scenario 5
f(a = 5)
# [1] FALSE

f(a = 5)
[1] TRUE

Test if an argument of a function is set or not in R

You use the function missing() for that.

f <- function(p1, p2) {
if(missing(p2)) {
p2=p1^2
}
p1-p2
}

Alternatively, you can set the value of p2 to NULL by default. I sometimes prefer that solution, as it allows for passing arguments to nested functions.

f <- function(p1, p2=NULL) {
if(is.null(p2)) {
p2=p1^2
}
p1-p2
}

f.wrapper <-function(p1,p2=NULL){
p1 <- 2*p1
f(p1,p2)
}
> f.wrapper(1)
[1] -2
> f.wrapper(1,3)
[1] -1

EDIT: you could do this technically with missing() as well, but then you would have to include a missing() statement in f.wrapper as well.

How to check if a variable is passed to a function with or without quotes?

This appears to work for all your cases:

myfun<-function(df,x){

sx <- substitute(x)
a <- tryCatch(is.character(x), error = function(e) FALSE)
if (a) {
new_x <- x
} else {
cx <- as.character(sx)
if (is.name(sx)) {
new_x <- cx
} else if (is.call(sx) && cx[1] == "c") {
new_x <- cx[-1]
} else {
stop("Invalid x")
}
}
new_args <- c(substitute(df), as.list(new_x))
do.call(printfun, new_args)
}

However, I feel there is something strange about what you are trying to do.

Check if the passed argument exists

One option is combining match.call (returns the call to the function) and all.vars (returns the names in an expression). Try this:

fcn <- function(x) {
varnames <- all.vars(match.call())
for (x in varnames)
stopifnot(exists(x))
}

fcn(a) # returns error, as expected
#Error: exists(x) is not TRUE

# create "a"
a <- 2
fcn(a + 1) # no error returned since "a" exists

Similarly,

fcn(a + b) # error returned since "b" does not exist
#Error: exists(x) is not TRUE
b <- 4
fcn(a + b) # no error since "b" now exists

in a user defined function in R, how do i check if inputs is of the right format in R?

If you want to "stop" if your argument is of length 1, and a real number

You could use stopifnot

foo <- function(x, y, z) {
stopifnot(length(x)==1L & is.numeric(x))
}

or perhaps

foo <- function(x, y, z){
if(!(length(x)==1L & is.numeric(x))) { stop("x must be a real number")}
}

stop allows you to specify the error message whereas stopifnot will return the condition that was tested. (Both have advantages)

The benefit of stopifnot is that it can tell you exactly which of multiple conditions failed.for example (noting that I am now feeding multiple expressions)

 foo <- function(x, y, z) {
stopifnot(length(x)==1L , is.numeric(x))
}

foo('a')
# Error: is.numeric(x) is not TRUE
foo(c(1,2))
# Error: length(x) == 1L is not TRUE

Argument checking in R

Have a look at ?stopifnot which does exactly what you want. It checks for the condition within and stops if the condition is not given. The same as in if, you can concatenate conditions with && or || and & amd |. See information with e.g. ?"&". Further helpful may also be all or any to check if all elements of a given vector fulfill the condition or any, respectively. Some examples:

foo <- function(A, B, C){
stopifnot(!missing(C), !missing(B), !missing(A)) ##A, B, C not missing, then continue
stopifnot(class(B)=="matrix") ## B is a matrix, then continue
stopifnot(class(B)==class(C), all(B > C)) ## class B is class C and all elements of B are greater than C
stopifnot((length(A)>1 && !any(is.na(A))) || all(A==0)) ## (A has more than 1 element and no element is NA) or all elements of A are 0.
stopifnot(all(A > 2), all(A < 10)) ## all elements of A are between 2 and 10, else stop.

#... further code
}

The conditions above may not fit together in this combination, but I think there are enough examples for you to adapt to your problem. Of course you could write all in one stopifnot, but it is more useful to group the conditions if there are many, because the condition which stops the function is printed as error code. So the more stopifnot you have, the more precise is the error information you get.



Related Topics



Leave a reply



Submit