Zmienne globalne i lokalne w R

Jestem nowicjuszem dla R i jestem trochę zdezorientowany z użyciem zmiennych lokalnych i globalnych w R.

Przeczytałem kilka postów w internecie, które mówią, że jeśli użyję = lub <- przypisam zmienną w bieżącym środowisku, a z <<- mogę uzyskać dostęp do zmiennej globalnej, gdy wewnątrz funkcji.

Jednak, jak pamiętam w C++ zmienne lokalne powstają za każdym razem, gdy deklarujesz zmienną w nawiasach {}, więc zastanawiam się, czy jest to to samo dla R? A może tylko dla funkcje W R, że mamy pojęcie zmiennych lokalnych.

Zrobiłem mały eksperyment, który wydaje się sugerować, że tylko nawiasy nie wystarczają, czy coś mi się stało?

{
   x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
 101
r
Author: Vokram, 2012-06-06

3 answers

Zmienne zadeklarowane wewnątrz funkcji są lokalne dla tej funkcji. Na przykład:

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

Podaje następujący błąd: Error: object 'bar' not found.

Jeśli chcesz stworzyć bar zmienną globalną, powinieneś wykonać:

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

W tym przypadku bar jest dostępna spoza funkcji.

Jednak, w przeciwieństwie do C, C++ i wielu innych języków, nawiasy nie określają zakresu zmiennych. Na przykład w poniższym fragmencie kodu:

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

y pozostaje dostępny po if-else oświadczenie.

Jak dobrze mówisz, możesz również tworzyć środowiska zagnieżdżone. Możesz spojrzeć na te dwa linki, aby zrozumieć, jak z nich korzystać:

  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

Oto mały przykład:

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
 122
Author: betabandido,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-05 20:44:31

<- wykonuje zadania w bieżącym środowisku.

Gdy jesteś wewnątrz funkcji R tworzy nowe środowisko dla Ciebie. Domyślnie zawiera wszystko ze środowiska, w którym został utworzony, więc można używać tych zmiennych, jak również, ale wszystko, co nowe tworzysz nie będzie zapisywane do środowiska globalnego.

W większości przypadków <<- przypisze zmienne już w środowisku globalnym lub utworzy zmienną w środowisku globalnym, nawet jeśli jesteś wewnątrz funkcja. Nie jest to jednak takie proste. To, co robi, to sprawdza środowisko macierzyste pod kątem zmiennej o nazwie zainteresowania. Jeśli nie znajdzie go w środowisku nadrzędnym, przechodzi do środowiska nadrzędnego (w czasie tworzenia funkcji) i tam wyszukuje. Jest ona kontynuowana w górę do środowiska globalnego i jeśli nie zostanie znaleziona w środowisku globalnym, przypisze zmienną do środowiska globalnego.

To może zilustrować, co jest dalej.

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"

Po raz pierwszy drukujemy pasek, którego jeszcze nie wywołaliśmy foo, więc nadal powinien być globalny - to ma sens. Drugi raz drukujemy go wewnątrz foo przed wywołaniem baz, więc wartość "in foo" ma sens. Poniżej widzimy, co <<- faktycznie robi. Następną wydrukowaną wartością jest " In baz-before <<-. Dzieje się tak dlatego, że <<- nie wygląda w bieżącym środowisku (chyba że jesteś w globalnym środowisko w którym <<- działa jak <-). Tak więc wewnątrz baz wartość bar pozostaje jako "in baz - beforebaz Kopia paska wewnątrz foo zostaje zmieniona na "IN baz", ale jak widzimy globalny bar pozostaje niezmieniony. Dzieje się tak dlatego, że kopia bar zdefiniowana wewnątrz foo znajduje się w środowisku nadrzędnym, gdy tworzymy baz, więc jest to pierwsza kopia bar, którą widzi <<- i tym samym Kopia, do której jest przypisana. Więc <<- to nie tylko bezpośrednie przypisanie do środowisko globalne.

<<- jest trudne i nie polecam go używać, jeśli można go uniknąć. Jeśli naprawdę chcesz przypisać do środowiska globalnego, możesz użyć funkcji Przypisz i powiedzieć jej wprost, że chcesz przypisać globalnie.

Teraz zmieniam <<- na polecenie assign i widzimy jaki to ma efekt:

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"

Więc oba razy drukujemy pasek wewnątrz foo wartość jest "in foo" nawet po wywołaniu baz. To dlatego, że assign nigdy nawet rozważaliśmy kopię bar wewnątrz foo, ponieważ powiedzieliśmy dokładnie, gdzie szukać. Jednak tym razem wartość bar w środowisku globalnym została zmieniona, ponieważ wyraźnie tam przypisaliśmy.

Teraz również pytałeś o tworzenie zmiennych lokalnych i możesz to zrobić dość łatwo, również bez tworzenia funkcji... Wystarczy użyć funkcji local.

bar <- "global"
# local will create a new environment for us to play in
local({
    bar <- "local"
    print(bar)
})
#[1] "local"
bar
#[1] "global"
 110
Author: Dason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-30 19:31:27

Trochę bardziej wzdłuż tych samych linii

attrs <- {}

attrs.a <- 1

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

f(20)
print(attrs.a)

Wydrukuje "1"

attrs <- {}

attrs.a <- 1

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

f(20)
print(attrs.a)

Wydrukuje "20"

 0
Author: SemanticBeeng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 07:47:29