I'd like to check if some variable is defined in R - without getting an error. How can I do this?
My attempts (not successful):
> is.na(ooxx)
Error: object 'ooxx' not found
> is.finite(ooxx)
Error: object 'ooxx' not found
Thanks!
You want exists()
:
R> exists("somethingUnknown")
[1] FALSE
R> somethingUnknown <- 42
R> exists("somethingUnknown")
[1] TRUE
R>
See ?exists
, for some definition of "...is defined". E.g.
> exists("foo")
[1] FALSE
> foo <- 1:10
> exists("foo")
[1] TRUE
if you are inside a function, missing() is what you want.
exchequer = function(x) {
if(missing(x)){
message("x is missing… :-(")
}
}
exchequer()
x is missing… :-(
missing
only works for function arguments, however. You can't do foo <- function(x) {missing(x); missing(y)}
or you will get foo(1)
> Error in missing(y) : 'missing' can only be used for arguments
.
As others have pointed out, you're looking for exists
. Keep in mind that using exists
with names used by R's base packages would return true regardless of whether you defined the variable:
> exists("data")
[1] TRUE
To get around this (as pointed out by Bazz; see ?exists
), use the inherits
argument:
> exists("data", inherits = FALSE)
[1] FALSE
foo <- TRUE
> exists("foo", inherits = FALSE)
[1] TRUE
Of course, if you wanted to search the name spaces of attached packages, this would also fall short:
> exists("data.table")
[1] FALSE
require(data.table)
> exists("data.table", inherits = FALSE)
[1] FALSE
> exists("data.table")
[1] TRUE
The only thing I can think of to get around this -- to search in attached packages but not in base packages -- is the following:
any(sapply(1:(which(search() == "tools:rstudio") - 1L),
function(pp) exists(_object_name_, where = pp, inherits = FALSE)))
Compare replacing _object_name_
with "data.table"
(TRUE
) vs. "var"
(FALSE
)
(of course, if you're not on RStudio, I think the first automatically attached environment is "package:stats"
)
inherits = FALSE
seems to isolate things in the global environment. Does that sound right?
If you don't want to use quotes, you can use deparse(substitute())
trick which I found in the example section of ?substitute
:
is.defined <- function(sym) {
sym <- deparse(substitute(sym))
env <- parent.frame()
exists(sym, env)
}
is.defined(a)
# FALSE
a <- 10
is.defined(a)
# TRUE
force
or evaluate it in the function like this: is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
Commented
Oct 4, 2017 at 0:49
NULL
for quosure (enquo(x)
if x is not null), you need a good way to check if the expression passed in is not null. Your solution does exactly that. thanks
If you don't mind using quotes, you can use:
exists("x")
If you don't want to use quotes you can use:
exists(deparse(substitute(x)))
There may be situations in which you do not exactly know the name of the variable you are looking for, like when an array of results have been created by a queuing system. These can possibly be addressed with "ls" and its argument "pattern" that expects a regular expression.
The "exists" function could be reimplemented that way as
exists <-function(variablename) {
#print(ls(env=globalenv()))
return(1==length(ls(pattern=paste("^",variablename,"$",sep=""),env=globalenv())))
}
While preparing this answer, I was a bit surprised about the need for the need of the specification of the environment when invoking ls() from within a function. So, thank you for that, stackoverflow! There is also an "all.names" attribute that I should have set to true but have omitted.