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
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ć:
- http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
- 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
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"
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"
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