372

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!

7 Answers 7

561

You want exists():

R> exists("somethingUnknown")
[1] FALSE
R> somethingUnknown <- 42
R> exists("somethingUnknown")
[1] TRUE
R> 
4
  • 39
    @tim if you are inside a function, missing() is what you want. Commented Jan 27, 2014 at 14:31
  • 2
    Might get a bit trickier if checking for list elements: stackoverflow.com/q/7719741
    – Tomas
    Commented Sep 20, 2014 at 11:58
  • 6
    what about for what the op wanted - using the variable name, not in quotes?
    – tim
    Commented Jun 13, 2015 at 13:46
  • @tim exists(quote(ooxx))
    – Julien
    Commented Dec 13, 2022 at 9:26
132

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

> exists("foo")
[1] FALSE
> foo <- 1:10
> exists("foo")
[1] TRUE
2
  • 12
    @DirkEddelbuettel Well, if you will use ridiculously long object names ;-) Commented Feb 20, 2012 at 21:54
  • 3
    heh. Happens to me all the time when I am testing out examples before posting, Gavin or Josh have already answered it.
    – Maiasaura
    Commented Feb 20, 2012 at 22:17
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… :-(
1
  • 8
    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.
    – Dannid
    Commented Feb 11, 2019 at 17:48
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")

3
  • 2
    Playing around, using argument inherits = FALSE seems to isolate things in the global environment. Does that sound right?
    – CJB
    Commented Jan 7, 2016 at 12:49
  • 1
    @Bazz you're correct; I've edited this into the answer. Commented Feb 3, 2016 at 3:21
  • 3
    This comment should be higher up, since I use variable name "data", just using exist gave me some trouble initially.
    – mzm
    Commented May 11, 2016 at 14:44
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
3
  • 1
    you can also force or evaluate it in the function like this: is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
    – chinsoon12
    Commented Oct 4, 2017 at 0:49
  • 2
    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-names
    – Gregg H
    Commented Jul 12, 2020 at 16:37
  • 1
    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. thanks
    – stucash
    Commented Nov 17, 2021 at 16:49
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)))

1
  • This answer combines previous answers. Not sure if this is adding anything to the conversation so far.
    – Nirmal
    Commented Nov 15, 2021 at 13:29
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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.