¿Cómo verificar si el objeto (variable) está definido en R?

294

Me gustaría verificar si alguna variable está definida en R, sin obtener un error. ¿Cómo puedo hacer esto?

Mis intentos (no exitosos):

> is.na(ooxx)
Error: object 'ooxx' not found
> is.finite(ooxx)
Error: object 'ooxx' not found

¡Gracias!

TMS
fuente

Respuestas:

448

Tu quieres exists():

R> exists("somethingUnknown")
[1] FALSE
R> somethingUnknown <- 42
R> exists("somethingUnknown")
[1] TRUE
R> 
Dirk Eddelbuettel
fuente
3
@Gavin y Dirk, son muy amables el uno con el otro :) ¡La única solución es tirar la moneda (Bernoulli con p = 0.5 :-)) que recibirá la aceptación! :-)
TMS
29
@tim si está dentro de una función, missing () es lo que desea.
CousinCocaine
2
Puede ser un poco más complicado si busca elementos de la lista: stackoverflow.com/q/7719741
TMS
55
¿Qué pasa con lo que el operador quería: usar el nombre de la variable, no entre comillas?
tim
109

Ver ?exists, para alguna definición de "... se define". P.ej

> exists("foo")
[1] FALSE
> foo <- 1:10
> exists("foo")
[1] TRUE
Gavin Simpson
fuente
77
Ganas
99
@DirkEddelbuettel Bueno, si vas a usar nombres de objetos ridículamente largos ;-)
Gavin Simpson
2
je Me sucede todo el tiempo cuando estoy probando ejemplos antes de publicar, Gavin o Josh ya lo han respondido.
Maiasaura
60

si está dentro de una función, falta () es lo que desea.

exchequer = function(x) {
    if(missing(x)){
        message("x is missing… :-(")
    }
}

exchequer()
x is missing… :-(
tim
fuente
missingSin embargo, solo funciona para argumentos de función. No puedes hacer foo <- function(x) {missing(x); missing(y)}o obtendrás foo(1) > Error in missing(y) : 'missing' can only be used for arguments.
Dannid
45

Como otros han señalado, estás buscando exists. Tenga en cuenta que usar existscon los nombres utilizados por los paquetes base de R devolvería verdadero independientemente de si definió la variable:

> exists("data")
[1] TRUE

Para evitar esto (como señaló Bazz; ver ?exists), use el inheritsargumento:

> exists("data", inherits = FALSE)
[1] FALSE

foo <- TRUE
> exists("foo", inherits = FALSE)
[1] TRUE

Por supuesto, si desea buscar los espacios de nombres de los paquetes adjuntos, esto también se quedaría corto:

> exists("data.table")
[1] FALSE
require(data.table)
> exists("data.table", inherits = FALSE)
[1] FALSE
> exists("data.table")
[1] TRUE

Lo único en lo que puedo pensar para evitar esto, para buscar en paquetes adjuntos pero no en paquetes básicos, es lo siguiente:

any(sapply(1:(which(search() == "tools:rstudio") - 1L),
           function(pp) exists(_object_name_, where = pp, inherits = FALSE)))

Comparar reemplazo _object_name_ con "data.table"( TRUE) vs. "var"( FALSE)

(por supuesto, si no estás en RStudio, creo que el primer entorno conectado automáticamente es "package:stats")

Sbaldrich
fuente
2
Jugar, usar argumentos inherits = FALSEparece aislar las cosas en el entorno global. ¿Eso suena bien?
CJB
1
@Bazz tienes razón; He editado esto en la respuesta.
MichaelChirico
2
Este comentario debería estar más arriba, ya que uso el nombre de variable "data", solo usar exist me dio algunos problemas inicialmente.
mzm
25

Si no desea usar comillas, puede usar el deparse(substitute())truco que encontré en la sección de ejemplos de ?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
Nirmal
fuente
1
también puede forceo evaluarlo en la función como esta:is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
chinsoon12
1

Puede haber situaciones en las que no sepa exactamente el nombre de la variable que está buscando, como cuando un sistema de colas ha creado una matriz de resultados. Posiblemente se puedan abordar con "ls" y su argumento "patrón" que espera una expresión regular.

La función "existe" podría reimplementarse de esa manera

exists <-function(variablename) {
   #print(ls(env=globalenv()))
   return(1==length(ls(pattern=paste("^",variablename,"$",sep=""),env=globalenv())))
}

Mientras preparaba esta respuesta, me sorprendió un poco la necesidad de la especificación del entorno al invocar ls () desde una función. Entonces, gracias por eso, stackoverflow! También hay un atributo "all.names" que debería haber establecido en verdadero pero que he omitido.

smoe
fuente