How to check if object (variable) is defined in R?
Asked Answered
J

7

370

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!

Jowers answered 20/2, 2012 at 21:46 Comment(0)
S
557

You want exists():

R> exists("somethingUnknown")
[1] FALSE
R> somethingUnknown <- 42
R> exists("somethingUnknown")
[1] TRUE
R> 
Sympetalous answered 20/2, 2012 at 21:51 Comment(4)
@tim if you are inside a function, missing() is what you want.Instinct
Might get a bit trickier if checking for list elements: https://mcmap.net/q/93469/-how-to-test-if-list-element-existsJowers
what about for what the op wanted - using the variable name, not in quotes?Fevre
@Fevre exists(quote(ooxx))Flatulent
W
132

See ?exists, for some definition of "...is defined". E.g.

> exists("foo")
[1] FALSE
> foo <- 1:10
> exists("foo")
[1] TRUE
Widener answered 20/2, 2012 at 21:50 Comment(2)
@DirkEddelbuettel Well, if you will use ridiculously long object names ;-)Widener
heh. Happens to me all the time when I am testing out examples before posting, Gavin or Josh have already answered it.Granoff
F
70

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… :-(
Fevre answered 9/3, 2013 at 21:56 Comment(1)
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.Electromyography
C
65

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")

Clarenceclarenceux answered 24/9, 2015 at 16:19 Comment(3)
Playing around, using argument inherits = FALSE seems to isolate things in the global environment. Does that sound right?Rooftop
@Bazz you're correct; I've edited this into the answer.Eiser
This comment should be higher up, since I use variable name "data", just using exist gave me some trouble initially.Southernly
P
40

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
Privy answered 17/4, 2017 at 6:32 Comment(3)
you can also force or evaluate it in the function like this: is.defined <- function(sym) class(try(sym, TRUE))!='try-error'Request
this answer may be a tad more complicated...but this is the ideal answer if you don't want to contend with characters vs var-namesCrockery
I have bumped into an issue that needs exactly your solution. When you wanted to use something that's not 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. thanksPinta
S
6

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)))

Soybean answered 18/5, 2021 at 15:24 Comment(1)
This answer combines previous answers. Not sure if this is adding anything to the conversation so far.Privy
G
2

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.

Gouveia answered 19/8, 2019 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.