Variabili globali e locali in R

Sono un novizio per R, e sono abbastanza confuso dall’uso di variabili locali e globali in R.

Ho letto alcuni post su internet che dicono se uso = o <- Assegnerò la variabile nell’ambiente corrente, e con <<- Posso accedere a una variabile globale quando all’interno di una funzione.

Tuttavia, come ricordo in C ++, le variabili locali sorgono ogni volta che dichiari una variabile tra parentesi {} , quindi mi chiedo se questo è lo stesso per R? O è solo per le funzioni in R che abbiamo il concetto di variabili locali.

Ho fatto un piccolo esperimento, il che sembra suggerire che solo le parentesi non sono sufficienti, sto ricevendo qualcosa di sbagliato?

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

Le variabili dichiarate all’interno di una funzione sono locali per quella funzione. Per esempio:

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

dà il seguente errore: Error: object 'bar' not found .

Se vuoi rendere bar una variabile globale, dovresti fare:

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

In questo caso la bar è accessibile dall'esterno della funzione.

Tuttavia, a differenza di C, C ++ o di molti altri linguaggi, le parentesi non determinano l'ambito delle variabili. Ad esempio, nel seguente frammento di codice:

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

y rimane accessibile dopo l'istruzione if-else .

Come dici tu, puoi anche creare ambienti nidificati. Puoi dare un'occhiata a questi due link per capire come usarli:

  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

Ecco un piccolo esempio:

 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 

<- esegue l'assegnazione nell'ambiente corrente.

Quando sei all'interno di una funzione R crea un nuovo ambiente per te. Di default include tutto dall'ambiente in cui è stato creato in modo da poter usare anche quelle variabili, ma nulla di nuovo creato non verrà scritto nell'ambiente globale.

Nella maggior parte dei casi <<- assegnerà alle variabili già nell'ambiente globale o creerà una variabile nell'ambiente globale anche se ci si trova all'interno di una funzione. Tuttavia, non è così semplice come quello. Quello che fa è controllare l'ambiente genitore per una variabile con il nome di interesse. Se non lo trova nell'ambiente genitore, passa al genitore dell'ambiente genitore (al momento della creazione della funzione) e guarda lì. Continua verso l'alto per l'ambiente globale e se non viene trovato nell'ambiente globale assegna la variabile nell'ambiente globale.

Questo potrebbe illustrare cosa sta succedendo.

 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" 

La prima volta che stampiamo la barra non abbiamo ancora chiamato foo quindi dovrebbe essere ancora globale - questo ha senso. La seconda volta che stampiamo è all'interno di foo prima di chiamare baz quindi il valore "in foo" ha senso. Quello che segue è dove vediamo ciò che <<- sta effettivamente facendo. Il prossimo valore stampato è "in baz - before << -" anche se l'istruzione print viene dopo il <<- . Questo perché <<- non guarda nell'ambiente corrente (a meno che tu non sia nell'ambiente globale nel qual caso <<- comporta come <- ). Quindi all'interno di baz il valore della barra rimane come "in baz - before << -". Una volta chiamata baz la copia della barra all'interno di foo viene modificata in "in baz", ma come possiamo vedere la bar globale è invariata. Questo perché la copia della bar definita all'interno di foo trova nell'ambiente genitore quando abbiamo creato baz quindi questa è la prima copia della bar che <<- vede e quindi la copia a cui assegna. Quindi <<- non è solo assegnando direttamente all'ambiente globale.

<<- È difficile e non consiglierei di usarlo se puoi evitarlo. Se si desidera veramente assegnare all'ambiente globale, è ansible utilizzare la funzione di assegnazione e indicare esplicitamente che si desidera assegnare globalmente.

Ora cambio il <<- in una dichiarazione di assegnazione e possiamo vedere quale effetto ha:

 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" 

Quindi entrambe le volte stampiamo la barra all'interno di foo il valore è "in foo" anche dopo aver chiamato baz . Questo perché assign non ha mai considerato nemmeno la copia della bar all'interno di foo perché gli abbiamo detto esattamente dove guardare. Tuttavia, questa volta il valore della barra nell'ambiente globale è stato modificato perché è stato esplicitamente assegnato lì.

Ora hai anche chiesto di creare variabili locali e puoi farlo abbastanza facilmente anche senza creare una funzione ... Abbiamo solo bisogno di usare la funzione local .

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

Un po ‘più lungo le stesse linee

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

stamperà "1"

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

Stamperà "20"