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
Change Level of Multiple Factor Variables
Lookup Values Corresponding to the Closest Date
Screening (Multi)Collinearity in a Regression Model
Piecewise Regression with R: Plotting the Segments
Save All Plots Already Present in the Panel of Rstudio
Real Time, Auto Updating, Incremental Plot in R
Cbind Warnings:Row Names Were Found from a Short Variable and Have Been Discarded
Using If Else Conditions on Vectors
Convert String Back into Object in R
Simple Manual Rmarkdown Tables That Look Good in HTML, PDF and Docx
To Find Whether a Column Exists in Data Frame or Not
Use R to Convert PDF Files to Text Files for Text Mining
How to Separate Title Page and Table of Content Page from Knitr Rmarkdown PDF
What's the Difference Between Hex Code (\X) and Unicode (\U) Chars