Come verificare se l'oggetto (variabile) è definito in R?


294

Vorrei verificare se alcune variabili sono definite in R - senza ottenere un errore. Come posso fare questo?

I miei tentativi (non riusciti):

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

Grazie!

Risposte:


448

Vuoi exists():

R> exists("somethingUnknown")
[1] FALSE
R> somethingUnknown <- 42
R> exists("somethingUnknown")
[1] TRUE
R> 

3
@Gavin & Dirk, sei così gentile l'uno con l'altro :) L'unica soluzione è che lanci la moneta (Bernoulli con p = 0,5 :-)) che otterrà l'accettazione! :-)
TMS

29
@tim se ti trovi all'interno di una funzione, missing () è quello che vuoi.
Cugina Cocaina,

2
Potrebbe essere un po 'più complicato se si controllano gli elementi dell'elenco: stackoverflow.com/q/7719741
TMS

5
che dire di ciò che voleva l'operazione - usando il nome della variabile, non tra virgolette?
tim

109

Vedi ?exists, per alcune definizioni di "... è definito". Per esempio

> exists("foo")
[1] FALSE
> foo <- 1:10
> exists("foo")
[1] TRUE

7
Vinci

9
@DirkEddelbuettel Bene, se userete nomi di oggetti ridicolmente lunghi ;-)
Gavin Simpson,

2
eh. Mi capita tutto il tempo in cui sto provando esempi prima di pubblicare, Gavin o Josh hanno già risposto.
Maiasaura,

60

se sei all'interno di una funzione, missing () è quello che vuoi.

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

exchequer()
x is missing… :-(

missingfunziona solo per argomenti di funzione, tuttavia. Non puoi fare foo <- function(x) {missing(x); missing(y)}o otterrai foo(1) > Error in missing(y) : 'missing' can only be used for arguments.
Dannid,

45

Come altri hanno sottolineato, stai cercando exists. Tieni presente che l'utilizzo existscon i nomi utilizzati dai pacchetti di base di R restituisce true indipendentemente dal fatto che tu abbia definito la variabile:

> exists("data")
[1] TRUE

Per aggirare questo (come sottolineato da Bazz; vedi ?exists), usa l' inheritsargomento:

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

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

Naturalmente, se si desidera cercare gli spazi dei nomi dei pacchetti allegati, anche questo non sarebbe:

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

L'unica cosa che mi viene in mente per aggirare questo problema - per cercare nei pacchetti allegati ma non nei pacchetti di base - è la seguente:

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

Confronta sostituendo _object_name_con "data.table"( TRUE) vs. "var"( FALSE)

(ovviamente, se non sei su RStudio, penso che il primo ambiente collegato automaticamente sia "package:stats")


2
Giocare, usare l'argomento inherits = FALSEsembra isolare le cose nell'ambiente globale. Suona bene?
CJB

1
@Bazz hai ragione; Ho modificato questo nella risposta.
MichaelChirico,

2
Questo commento dovrebbe essere più in alto, dato che uso il nome variabile "data", il solo utilizzo di mi ha dato inizialmente dei problemi.
mzm,

25

Se non vuoi usare le virgolette, puoi usare il deparse(substitute())trucco che ho trovato nella sezione di esempio di ?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

1
puoi anche forceo valutarlo nella funzione in questo modo:is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
chinsoon12

1

Potrebbero verificarsi situazioni in cui non si conosce esattamente il nome della variabile che si sta cercando, ad esempio quando un array di risultati è stato creato da un sistema di accodamento. Questi possono eventualmente essere affrontati con "ls" e il suo argomento "pattern" che prevede un'espressione regolare.

La funzione "esiste" potrebbe essere reimplementata in questo modo come

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

Durante la preparazione di questa risposta, sono rimasto un po 'sorpreso dalla necessità di specificare l'ambiente quando invoco ls () dall'interno di una funzione. Quindi, grazie per quello, StackOverflow! C'è anche un attributo "all.names" che avrei dovuto impostare su true ma ho omesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.