Globale und lokale Variablen in R.


126

Ich bin ein Neuling für R, und ich bin ziemlich verwirrt mit der Verwendung lokaler und globaler Variablen in R.

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

Wie ich mich in C ++ erinnere, treten lokale Variablen jedoch immer dann auf, wenn Sie eine Variable in Klammern deklarieren. {}Ich frage mich also, ob dies für R gleich ist. Oder haben wir nur für Funktionen in R das Konzept lokaler Variablen?

Ich habe ein kleines Experiment durchgeführt, das darauf hindeutet, dass nur Klammern nicht ausreichen. Verstehe ich etwas falsch?

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

Einige Code, die zusätzlich zu diesen Antworten ausgeführt werden sollen : globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env,…
Isomorphismen

@isomorphismes , Error: could not find function "%>%". Ist das eine andere Form der Zuordnung?
Aaron McDaid

1
Relevanter Thread zur R-Hilfe: Was bedeutet der Operator "<< -"? .
Henrik

1
@ AaronMcDaid Hallo, entschuldige, dass du nicht früher geantwortet hast! Das ist von require(magrittr). Es ist eine Möglichkeit, Funktionen rechts ( x | f1 | f2 | f3) statt links ( f3( f2( f1( x ) ) )) anzuwenden .
Isomorphismen

Antworten:


153

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

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

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

Wenn Sie bareine globale Variable erstellen möchten , sollten Sie Folgendes tun:

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

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

Im Gegensatz zu C, C ++ oder vielen anderen Sprachen bestimmen Klammern jedoch nicht den Umfang der Variablen. Zum Beispiel im folgenden Codefragment:

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

ybleibt nach der if-elseAussage zugänglich .

Wie Sie bereits sagen, können Sie auch verschachtelte Umgebungen erstellen. Sie können sich diese beiden Links ansehen, um zu verstehen, wie man sie verwendet:

  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

136

<- erledigt die Zuordnung in der aktuellen Umgebung.

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

In den meisten Fällen <<-werden Variablen zugewiesen, die sich bereits in der globalen Umgebung befinden, oder es wird eine Variable in der globalen Umgebung erstellt, 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 Ihrer übergeordneten Umgebung nicht gefunden wird, geht es zum übergeordneten Element der übergeordneten Umgebung (zum Zeitpunkt der Erstellung der Funktion) und sucht dort. Es geht weiter nach oben in die globale Umgebung. Wenn es in der globalen Umgebung nicht gefunden wird, wird die Variable in der globalen Umgebung zugewiesen.

Dies könnte veranschaulichen, was los ist.

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, wenn wir eine Leiste drucken, haben wir noch nicht angerufen, foodaher sollte sie immer noch global sein - das ist sinnvoll. Das zweite Mal, wenn wir es drucken, ist es innerhalb von, foobevor wir es aufrufen, bazsodass der Wert "in foo" Sinn macht. Im Folgenden sehen wir, was <<-tatsächlich geschieht. Der nächste gedruckte Wert ist "in baz - vor << -", obwohl die print-Anweisung nach dem steht <<-. Dies liegt daran , <<-nicht in der aktuellen Umgebung suchen (es sei denn , Sie in der globalen Umgebung sind in diesem Fall <<-verhält sich wie <-). Innerhalb des bazWertes von bar bleibt also "in baz - vor << -". Sobald wir bazdie Kopie der Leiste innerhalb von aufrufen, foowird sie in "in baz" geändert, aber wie wir sehen können, barbleibt die globale unverändert.barDas, was innerhalb von definiert ist, foobefindet sich in der übergeordneten Umgebung, als wir es erstellt bazhaben. Dies ist also die erste Kopie bar, die <<-angezeigt wird, und somit die Kopie, der es zugewiesen ist. Es <<-wird also nicht nur direkt der globalen Umgebung zugewiesen.

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

Jetzt ändere ich die <<-zu einer Assign-Anweisung und wir können sehen, welchen Effekt 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, foowenn wir einen Balken innerhalb des Werts drucken, ist dies auch nach dem Aufruf "in foo" baz. Dies liegt daran, dass wir assigndie Kopie von barinside of foo noch nie in Betracht gezogen haben, weil wir genau gesagt haben, wo wir suchen sollen. Diesmal wurde jedoch der Wert von bar in der globalen Umgebung geändert, da wir ihn dort explizit zugewiesen haben.

Jetzt haben Sie auch nach dem Erstellen lokaler Variablen gefragt, und Sie können dies auch ziemlich einfach tun, ohne eine Funktion zu erstellen ... Wir müssen nur die localFunktion verwenden.

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

2

Ein bisschen mehr in die gleiche Richtung

attrs <- {}

attrs.a <- 1

f <- function(d) {
    attrs.a <- d
}

f(20)
print(attrs.a)

druckt "1"

attrs <- {}

attrs.a <- 1

f <- function(d) {
   attrs.a <<- d
}

f(20)
print(attrs.a)

Druckt "20"

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.