Wie prüfe ich, ob Objekt (Variable) in R definiert ist?


294

Ich möchte überprüfen, ob eine Variable in R definiert ist - ohne einen Fehler zu erhalten. Wie kann ich das machen?

Meine Versuche (nicht erfolgreich):

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

Vielen Dank!

Antworten:


448

Sie wollen exists():

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

3
@ Gavin & Dirk, du bist so nett zueinander :) Die einzige Lösung ist, dass du die Münze wirfst (Bernoulli mit p = 0,5 :-)), die die Annahme bekommt! :-)
TMS

29
@tim Wenn Sie sich in einer Funktion befinden, möchten Sie () ().
CousinCocaine


5
Was ist mit dem, was die Operation wollte - mit dem Variablennamen, nicht in Anführungszeichen?
Tim

109

Siehe ?existsfür eine Definition von "... ist definiert". Z.B

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

7
Sie gewinnen mit 52 Sekunden :)
Dirk Eddelbuettel

9
@ KirkEddelbuettel Nun, wenn Sie lächerlich lange Objektnamen verwenden ;-)
Gavin Simpson

2
heh. Passiert mir die ganze Zeit, wenn ich Beispiele vor dem Posten teste, haben Gavin oder Josh bereits darauf geantwortet.
Maiasaura

60

Wenn Sie sich in einer Funktion befinden, möchten Sie (() nicht ().

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

exchequer()
x is missing… :-(

missingfunktioniert jedoch nur für Funktionsargumente. Sie können nicht tun foo <- function(x) {missing(x); missing(y)}oder Sie werden bekommen foo(1) > Error in missing(y) : 'missing' can only be used for arguments.
Dannid

45

Wie andere betont haben, suchen Sie exists. Beachten Sie, dass die Verwendung existsmit Namen, die von Rs Basispaketen verwendet werden, true zurückgibt, unabhängig davon, ob Sie die Variable definiert haben:

> exists("data")
[1] TRUE

?existsVerwenden Sie das folgende inheritsArgument , um dies zu umgehen (wie von Bazz hervorgehoben; siehe ).

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

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

Wenn Sie die Namensräume angehängter Pakete durchsuchen möchten, ist dies natürlich auch nicht ausreichend:

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

Das einzige, was ich mir vorstellen kann, um dies zu umgehen - in angehängten Paketen zu suchen, aber nicht in Basispaketen - ist das Folgende:

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

Vergleiche Ersetzen _object_name_mit "data.table"( TRUE) vs. "var"( FALSE)

(Wenn Sie nicht auf RStudio sind, ist die erste automatisch angehängte Umgebung natürlich "package:stats")


2
Das Herumspielen und Verwenden von Argumenten inherits = FALSEscheint die Dinge in der globalen Umgebung zu isolieren. Klingt das richtig?
CJB

1
@Bazz du bist richtig; Ich habe dies in der Antwort bearbeitet.
MichaelChirico

2
Dieser Kommentar sollte weiter oben stehen, da ich den Variablennamen "data" verwende. Die Verwendung von exist gab mir anfangs einige Probleme.
MZM

25

Wenn Sie keine Anführungszeichen verwenden möchten, können Sie einen deparse(substitute())Trick verwenden, den ich im Beispielabschnitt von ?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
Sie können es auch forceoder in der Funktion wie is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
folgt

1

Es kann Situationen geben, in denen Sie den Namen der gesuchten Variablen nicht genau kennen, z. B. wenn ein Warteschlangensystem eine Reihe von Ergebnissen erstellt hat. Diese können möglicherweise mit "ls" und seinem Argument "pattern" angesprochen werden, das einen regulären Ausdruck erwartet.

Die Funktion "existiert" könnte auf diese Weise wie folgt neu implementiert werden

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

Während ich diese Antwort vorbereitete, war ich ein wenig überrascht über die Notwendigkeit, die Spezifikation der Umgebung zu benötigen, wenn ls () innerhalb einer Funktion aufgerufen wird . Also, danke dafür, Stackoverflow! Es gibt auch ein "all.names" -Attribut, das ich auf true hätte setzen sollen, aber weggelassen habe.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.