2012-06-05 21 views
89

Ich bin ein Neuling für R, und ich bin ganz mit der Nutzung von lokalen und globalen Variablen in R. verwirrtGlobale und lokale Variablen in R

ich einige Beiträge im Internet gelesen, die sagt, wenn ich = oder <- Ich werde die Variable in der aktuellen Umgebung zuweisen, und mit <<- kann ich auf eine globale Variable innerhalb einer Funktion zugreifen.

Allerdings, wie ich mich erinnere in C++ lokale Variablen auftreten, wenn Sie eine Variable in Klammern {} deklarieren, so frage ich mich, ob das gleiche für R ist? Oder ist es nur für Funktionen in R, dass wir das Konzept der lokalen Variablen haben.

Ich habe ein kleines Experiment gemacht, was nahelegt, dass nur Brackets nicht ausreichen, bekomme ich irgendetwas falsch?

{ 
    x=matrix(1:10,2,5) 
} 
print(x[2,2]) 
[1] 4 
+0

Ein Code, der zusätzlich zu diesen Antworten ausgeführt wird: 'globlenv(); globalenv()%>% parent.env; globenv()%>% parent.env%>% parent.env', ... – isomorphismes

+0

@isomorphismen, 'Fehler: konnte die Funktion"%>% "' nicht finden. Ist das eine andere Form der Zuweisung? –

+1

Relevanter Thread zu R-help: [** Was bedeutet der Operator "<< -"? **] (http://r.789695.n4.nabble.com/What-does-the-quot-lt- lt-quote-operator-mean-td3466657.html). – Henrik

Antwort

105

In einer Funktion deklarierte Variablen sind lokal für diese Funktion. Zum Beispiel:

foo <- function() { 
    bar <- 1 
} 
foo() 
bar 

gibt den folgenden Fehler: Error: object 'bar' not found.

Wenn Sie bar eine globale Variable machen wollen, sollten Sie tun:

foo <- function() { 
    bar <<- 1 
} 
foo() 
bar 

In diesem Fall bar von außerhalb der Funktion zugänglich ist.

Im Gegensatz zu C, C++ oder vielen anderen Sprachen bestimmen eckige Klammern jedoch nicht den Umfang der Variablen. Zum Beispiel in dem folgenden Code-Schnipsel:

if (x > 10) { 
    y <- 0 
} 
else { 
    y <- 1 
} 

y zugänglich bleibt nach der if-else Aussage.

Wie Sie gut sagen, können Sie auch verschachtelte Umgebungen erstellen. Sie können für das Verständnis bei diesen beiden Verbindungen haben einen Blick, wie sie benutzen:

  1. http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
  2. http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html

Hier haben Sie ein kleines Beispiel:

test.env <- new.env() 

assign('var', 100, envir=test.env) 
# or simply 
test.env$var <- 100 

get('var') # var cannot be found since it is not defined in this environment 
get('var', envir=test.env) # now it can be found 
+0

In Ihrem zweiten Beispiel müssten Sie foo() aufrufen, bevor Sie versuchen, auf die Leiste zuzugreifen. Aber "<< -" ist nicht ganz so einfach, wie Sie das OP zu glauben glauben. – Dason

+0

@Dason in der Tat :) Ich habe den Aufruf der Funktion vergessen ... – betabandido

+0

Ich habe meinen Kommentar bearbeitet, um klarer zu machen, was ich meinte. – Dason

99

<- tut Zuordnung in der aktuellen Umgebung.

Wenn Sie in einer Funktion sind, erstellt R eine neue Umgebung für Sie. Standardmäßig enthält es alles aus der Umgebung, in der es erstellt wurde, so dass Sie diese Variablen ebenfalls verwenden können, aber alles, was Sie neu erstellen, wird nicht in die globale Umgebung geschrieben.

In den meisten Fällen wird <<- Variablen zuweisen, die bereits in der globalen Umgebung vorhanden sind, oder eine Variable in der globalen Umgebung erstellen, selbst wenn Sie sich in einer Funktion befinden. Es ist jedoch nicht ganz so einfach. Es überprüft die übergeordnete Umgebung auf eine Variable mit dem Namen von Interesse. Wenn es in der übergeordneten Umgebung nicht gefunden wird, wird es zum übergeordneten Element der übergeordneten Umgebung (zum Zeitpunkt der Erstellung der Funktion) angezeigt und dort angezeigt.Es geht weiter nach oben zur globalen Umgebung und wenn es nicht in der globalen Umgebung gefunden wird, wird es die Variable in der globalen Umgebung zuweisen.

Dies könnte veranschaulichen, was vor sich geht.

bar <- "global" 
foo <- function(){ 
    bar <- "in foo" 
    baz <- function(){ 
     bar <- "in baz - before <<-" 
     bar <<- "in baz - after <<-" 
     print(bar) 
    } 
    print(bar) 
    baz() 
    print(bar) 
} 
> bar 
[1] "global" 
> foo() 
[1] "in foo" 
[1] "in baz - before <<-" 
[1] "in baz - after <<-" 
> bar 
[1] "global" 

Das erste Mal, dass wir bar Druck haben wir nicht foo noch genannt, so dass es noch global sein sollte - das macht Sinn. Das zweite Mal drucken wir es innerhalb von foo vor dem Aufruf baz, so dass der Wert "in foo" sinnvoll ist. Im Folgenden sehen wir, was <<- tatsächlich macht. Der nächste gedruckte Wert ist "in baz - vor < < -", obwohl die Druckanweisung nach der <<- kommt. Dies liegt daran, dass <<- in der aktuellen Umgebung nicht angezeigt wird (es sei denn, Sie befinden sich in der globalen Umgebung. In diesem Fall verhält sich <<- wie <-). Innerhalb von baz bleibt der Wert von bar wie "in baz - vor < < -". Sobald wir baz anrufen, wird die Kopie der Bar innerhalb von foo zu "in baz" geändert, aber wie wir sehen können, ist der globale bar unverändert. Das liegt daran, dass die Kopie von bar, die in foo definiert ist, sich in der übergeordneten Umgebung befindet, als wir baz erstellten. Dies ist also die erste Kopie von bar, die <<- sieht und somit die Kopie zuweist. So ordnet <<- nicht nur direkt der globalen Umgebung zu.

<<- ist schwierig und ich würde nicht empfehlen, es zu verwenden, wenn Sie es vermeiden können. Wenn Sie der globalen Umgebung wirklich zuweisen möchten, können Sie die Zuweisungsfunktion verwenden und explizit angeben, dass Sie global zuweisen möchten.

Jetzt wechsle ich die <<- zu einer assign Aussage und wir können sehen, welche Wirkung das hat:

bar <- "global" 
foo <- function(){ 
    bar <- "in foo" 
    baz <- function(){ 
     assign("bar", "in baz", envir = .GlobalEnv) 
    } 
    print(bar) 
    baz() 
    print(bar) 
} 
bar 
#[1] "global" 
foo() 
#[1] "in foo" 
#[1] "in foo" 
bar 
#[1] "in baz" 

beide Male wir bar So drucken innerhalb von foo der Wert „in foo“ auch nach baz aufrufen. Dies ist, weil assign nie die Kopie von bar innerhalb von foo betrachtet, weil wir es genau gesagt haben, wo man hinschauen soll. Diesmal wurde jedoch der Wert von bar in der globalen Umgebung geändert, weil wir ihn explizit zugewiesen haben.

Jetzt haben Sie auch gefragt, wie Sie lokale Variablen erstellen können, und Sie können das auch ziemlich einfach tun, ohne eine Funktion zu erstellen ... Wir müssen nur die local Funktion verwenden.

bar <- "global" 
# local will create a new environment for us to play in 
local({ 
    bar <- "local" 
    print(bar) 
}) 
#[1] "local" 
bar 
#[1] "global"