Jak używać "< < - " (przypisanie zakresu) W R?

Właśnie skończyłem czytać oscopingu w intro R i jestem bardzo ciekawy <<- zadania.

Instrukcja pokazała jeden (bardzo ciekawy) przykład <<-, który wydaje mi się zrozumiały. Wciąż brakuje mi kontekstu, kiedy może to być przydatne.

Więc to, co chciałbym przeczytać od ciebie, to przykłady (lub linki do przykładów) na temat, kiedy użycie <<- może być interesujące/przydatne. Jakie mogą być niebezpieczeństwa związane z jego użyciem (wygląda na to, że łatwo stracić ślad), i wszelkie wskazówki, którymi możesz się podzielić.

Author: Bhargav Rao, 2010-04-13

6 answers

<<- jest najbardziej przydatny w połączeniu z zamknięciami w celu utrzymania stanu. Oto fragment mojej ostatniej pracy:

Zamknięcie jest funkcją zapisaną przez inną funkcję. Zamknięcia są tak nazywane, ponieważ zawierają środowisko funkcji nadrzędnej i mogą uzyskać dostęp do wszystkich zmiennych i parametrów w tej funkcji. Jest to przydatne, ponieważ pozwala nam mieć dwa poziomy parametrów. Jeden poziom parametrów (rodzic) kontroluje działanie funkcji. Inne poziom (dziecko) wykonuje pracę. Poniższy przykład pokazuje, jak można wykorzystać ten pomysł do wygenerowania rodziny funkcji mocy. Funkcja rodzica (power) tworzy funkcje potomne (square i cube), które faktycznie wykonują ciężką pracę.

power <- function(exponent) {
  function(x) x ^ exponent
}

square <- power(2)
square(2) # -> [1] 4
square(4) # -> [1] 16

cube <- power(3)
cube(2) # -> [1] 8
cube(4) # -> [1] 64

Możliwość zarządzania zmiennymi na dwóch poziomach umożliwia również utrzymanie stanu w różnych wywołaniach funkcji, pozwalając funkcji modyfikować zmienne w środowisku rodzica. Kluczem do zarządzania zmiennymi na różnych poziomach jest operator przypisania strzałki podwójnej <<-. W przeciwieństwie do zwykłego przypisania pojedynczej strzałki (<-), które zawsze działa na bieżącym poziomie, operator podwójnej strzałki może modyfikować zmienne na poziomach nadrzędnych.

Umożliwia to utrzymanie licznika, który rejestruje, ile razy funkcja została wywołana, jak pokazuje poniższy przykład. Za każdym razem, gdy new_counter jest uruchomiony, tworzy środowisko, inicjuje licznik i w tym środowisku, a następnie tworzy nową funkcję.

new_counter <- function() {
  i <- 0
  function() {
    # do something useful, then ...
    i <<- i + 1
    i
  }
}

Nowa funkcja jest zamknięciem, a jej środowisko jest otoczeniem. Po uruchomieniu zamknięć counter_one i counter_two, każdy z nich modyfikuje licznik w otaczającym go środowisku, a następnie zwraca bieżącą liczbę.

counter_one <- new_counter()
counter_two <- new_counter()

counter_one() # -> [1] 1
counter_one() # -> [1] 2
counter_two() # -> [1] 1
 148
Author: hadley,
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
2014-04-28 12:09:40

Pomaga myśleć <<- jako odpowiednik assign (Jeśli ustawisz parametr inherits w tej funkcji na TRUE). Zaletą assign jest to, że pozwala określić więcej parametrów (np. środowisko), więc wolę używać assign zamiast <<- w większości przypadków.

Użycie <<- i assign(x, value, inherits=TRUE) oznacza, że "environments of the provided environment are searched until the variable' x ' is methoded."Innymi słowy, będzie przechodzić przez otoczenie w kolejności, aż do wyszukuje zmienną o tej nazwie i do niej ją przypisze. Może to być w ramach funkcji lub w środowisku globalnym.

Aby zrozumieć, do czego służą te funkcje, musisz również zrozumieć środowiska R(np. używając search).

Regularnie korzystam z tych funkcji, gdy uruchamiam dużą symulację i chcę zapisać wyniki pośrednie. Pozwala to na wytworzenie obiektu poza zakresem danej funkcji lub pętli apply. To bardzo pomocne, zwłaszcza jeśli masz jakiekolwiek obawy o nieoczekiwane zakończenie dużej pętli (np. odłączenie bazy danych), w którym to przypadku możesz stracić wszystko w procesie. Byłoby to równoważne zapisywaniu wyników do bazy danych lub pliku podczas długotrwałego procesu, z tym wyjątkiem, że zamiast tego przechowuje wyniki w środowisku R.

Moje główne Ostrzeżenie: bądź ostrożny, ponieważ pracujesz teraz ze zmiennymi globalnymi, zwłaszcza gdy używasz <<-. To znaczy że możesz skończyć z sytuacjami, w których funkcja używa wartości obiektu z otoczenia, kiedy spodziewałeś się, że będzie używać takiej, która została dostarczona jako parametr. Jest to jedna z głównych rzeczy, której programowanie funkcjonalne próbuje uniknąć (zobacz skutki uboczne). Unikam tego problemu, przypisując moje wartości do unikalnych nazw zmiennych (za pomocą pasty z zestawem lub unikalnych parametrów), które nigdy nie są używane w funkcji, ale po prostu używane do buforowania i w razie potrzeby Odzyskaj później (lub wykonaj metaanalizę wyników pośrednich).

 29
Author: Shane,
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
2010-04-13 13:59:05

Jedno miejsce, gdzie użyłem {[1] } było w prostych GUI za pomocą tcl / tk. Niektóre z początkowych przykładów mają to -- ponieważ musisz dokonać rozróżnienia między zmiennymi lokalnymi i globalnymi dla statefullness. Zobacz na przykład

 library(tcltk)
 demo(tkdensity)

Który używa <<-. W przeciwnym razie zgadzam się z Markiem :) -- wyszukiwarka Google może pomóc.

 5
Author: Dirk Eddelbuettel,
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
2010-04-13 12:12:30
f <- function(n, x0) {x <- x0; replicate(n, (function(){x <<- x+rnorm(1)})())}
plot(f(1000,0),typ="l")
 4
Author: lcgong,
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
2010-04-13 12:23:22

Operator <<- może być również przydatny dla klas referencyjnych przy pisaniu metod referencyjnych . Na przykład:

myRFclass <- setRefClass(Class = "RF",
                         fields = list(A = "numeric",
                                       B = "numeric",
                                       C = function() A + B))
myRFclass$methods(show = function() cat("A =", A, "B =", B, "C =",C))
myRFclass$methods(changeA = function() A <<- A*B) # note the <<-
obj1 <- myRFclass(A = 2, B = 3)
obj1
# A = 2 B = 3 C = 5
obj1$changeA()
obj1
# A = 6 B = 3 C = 9
 2
Author: Carlos Cinelli,
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
2015-06-15 15:12:24

W tym temacie chciałbym zaznaczyć, że operator

fortest <- function() {
    mySum <- 0
    for (i in c(1, 2, 3)) {
        mySum <<- mySum + i
    }
    mySum
}

Można oczekiwać, że funkcja zwróci oczekiwaną sumę, 6, ale zamiast tego zwraca 0, a zmienna globalna mySum jest tworzona i przypisywana wartości 3. Nie mogę w pełni wyjaśnić, o co tu chodzi, ale z pewnością ciało pętli for jest , a nie nowym 'poziomem'zakresu. Zamiast tego, wydaje się, że R wygląda poza funkcją fortest, nie może znaleźć zmiennej mySum do przypisania, więc tworzy jedną i przypisuje wartość 1, za pierwszym razem przez pętlę. W kolejnych iteracjach RHS w przypisaniu musi odnosić się do (niezmienionej) wewnętrznej zmiennej mySum, podczas gdy LHS odnosi się do zmiennej globalnej. Dlatego każda iteracja nadpisuje wartość zmiennej globalnej do wartości i, stąd ma wartość 3 przy wyjściu z funkcja.

Mam nadzieję, że to komuś pomoże - to mnie dziwi przez kilka godzin! (BTW, wystarczy wymienić

 2
Author: Matthew Wise,
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
2017-10-03 20:50:12