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:
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"