Variables globales y locales en R

Soy un novato para R, y estoy bastante confundido con el uso de variables locales y globales en R.

Leí algunas publicaciones en Internet que dicen que si uso = o <- asignaré la variable en el entorno actual, y con <<- puedo acceder a una variable global cuando estoy dentro de una función.

Sin embargo, como recuerdo en C ++, surgen variables locales cada vez que declaras una variable entre paréntesis {} , entonces me pregunto si esto es lo mismo para R? ¿O es solo para funciones en R que tenemos el concepto de variables locales?

Hice un pequeño experimento, lo que parece sugerir que solo los corchetes no son suficientes, ¿estoy obteniendo algo mal?

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

Las variables declaradas dentro de una función son locales para esa función. Por ejemplo:

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

da el siguiente error: Error: object 'bar' not found .

Si desea hacer que bar una variable global, debe hacer:

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

En este caso bar se puede acceder a la bar desde fuera de la función.

Sin embargo, a diferencia de C, C ++ o muchos otros lenguajes, los corchetes no determinan el scope de las variables. Por ejemplo, en el siguiente fragmento de código:

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

y sigue siendo accesible después de la statement if-else .

Como bien dices, también puedes crear entornos nesteds. Puede echar un vistazo a estos dos enlaces para comprender cómo usarlos:

  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

Aquí tienes un pequeño ejemplo:

 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 

< - hace la asignación en el entorno actual.

Cuando estás dentro de una función, R crea un nuevo entorno para ti. Por defecto, incluye todo desde el entorno en el que fue creado para que pueda usar esas variables también, pero cualquier cosa nueva que cree no se escribirá en el entorno global.

En la mayoría de los casos < <- asignará las variables que ya están en el entorno global o creará una variable en el entorno global, incluso si está dentro de una función. Sin embargo, no es tan sencillo como eso. Lo que hace es verificar el entorno principal para una variable con el nombre de interés. Si no lo encuentra en su entorno primario, va al padre del entorno principal (en el momento en que se creó la función) y se ve allí. Continúa hacia arriba en el entorno global y, si no se encuentra en el entorno global, asignará la variable en el entorno global.

Esto podría ilustrar lo que está sucediendo.

 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 primera vez que imprimimos la barra, no hemos llamado a foo por lo que aún debería ser global; esto tiene sentido. La segunda vez que imprimimos está dentro de foo antes de llamar a baz así que el valor "in foo" tiene sentido. A continuación es donde vemos qué < <- está realmente haciendo. El siguiente valor impreso es "in baz - before < < -" aunque la instrucción print viene después de < <- . Esto se debe a que < <- no se ve en el entorno actual (a menos que se encuentre en el entorno global, en cuyo caso < <- actúa como < - ). Entonces, dentro de baz el valor de la barra permanece como "en baz - antes < < -". Una vez que llamamos baz la copia de la barra dentro de foo cambia a "in baz", pero como podemos ver, la bar global no cambia. Esto se debe a que la copia de la bar que se define dentro de foo está en el entorno principal cuando creamos baz así que esta es la primera copia de la bar que < <- ve y, por lo tanto, la copia que asigna. Entonces < <- no es solo asignar directamente al entorno global.

< <- es complicado y no recomendaría usarlo si puedes evitarlo. Si realmente desea asignar al entorno global, puede usar la función de asignación e indicar explícitamente que desea asignar globalmente.

Ahora cambio el < <- a una statement de asignación y podemos ver qué efecto tiene:

 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" 

Entonces, las dos veces que imprimimos la barra dentro de foo el valor es "in foo" incluso después de llamar a baz . Esto es porque assign nunca consideró la copia de la bar dentro de foo porque le dijimos exactamente dónde mirar. Sin embargo, esta vez el valor de la barra en el entorno global se modificó porque allí se asignó explícitamente.

Ahora también preguntaste sobre la creación de variables locales y también puedes hacerlo con bastante facilidad sin crear una función ... Solo necesitamos usar la función 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 poco más en la misma línea

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

imprimirá "1"

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

Se imprimirá "20"