Jakie są różnice między operatorami " = " i "< - " w R?
Jakie są różnice między operatorami przypisania =
i <-
W R?
Wiem, że operatory są nieco inne, jak pokazuje ten przykład
x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"
Ale czy to jedyna różnica? 7 answers
Jakie są różnice między operatorami przypisania
=
i<-
W R?
Jak pokazuje Twój przykład, =
i <-
mają nieco inny priorytet operatora (który określa kolejność oceny, gdy są mieszane w tym samym wyrażeniu). W rzeczywistości, ?Syntax
W R podaje następującą tabelę pierwszeństwa operatora, od najwyższego do najniższego:
… ‘-> ->>’ rightwards assignment ‘<- <<-’ assignment (right to left) ‘=’ assignment (right to left) …
Ale czy to jedyna różnica?
Skoro pytałeś o operatory przypisania : tak, to jedyna różnica. Wybaczono by Ci jednak, że wierzysz w coś innego. Nawet dokumentacja R?assignOps
twierdzi, że jest więcej różnic:
Operator
<-
może być używany wszędzie, natomiast operator=
jest dozwolony tylko na najwyższym poziomie (np., w pełnym wyrażeniu wpisanym w wierszu polecenia) lub jako jeden z podwyrażeń w rozwiniętej liście wyrażeń.
Nie stawiajmy zbyt dobra uwaga: dokumentacja R jest zła . Jest to łatwe do pokazania: musimy tylko znaleźć kontrprzykład operatora =
, który nie jest (a) na najwyższym poziomie, ani (b) podwyrażeniem w usztywnionej liście wyrażeń (np. {…; …}
). - Bez zbędnych ceregieli:
x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1
Najwyraźniej wykonaliśmy zadanie, używając =
, poza kontekstami (a) i (b). Dlaczego więc dokumentacja podstawowej funkcji języka R była błędna od dziesięcioleci?
To dlatego, że w składni R symbol =
ma dwa różne znaczenia, które są rutynowo ze sobą powiązane (nawet przez ekspertów, w tym w dokumentacji przytoczonej powyżej):
- pierwsze znaczenie ma operator przypisania . To wszystko, o czym do tej pory rozmawialiśmy.
- drugie znaczenie nie jest operatorem, ale raczej tokenem składni , który sygnalizuje nazwany argument przekazujący w wywołaniu funkcji. W przeciwieństwie do
=
operator nie wykonuje żadnej akcji w czasie wykonywania, jedynie zmienia sposób przetwarzania wyrażenia.
Więc jak R decyduje, czy dane użycie =
odnosi się do operatora, czy do nazwanego przekazania argumentu? Zobaczmy.
W dowolnym fragmencie kodu postaci ogólnej ...
‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)
... the =
jest tokenem, który definiuje nazwane przekazywanie argumentów: jest , a nie operatorem przypisania. Ponadto, {[6] } jest całkowicie zabronione w niektórych kontekstach składniowych:
if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …
Każdy z nich spowoduje błąd "unexpected" = "w " bla"".
W innym kontekście, =
odnosi się do wywołania operatora przypisania. W szczególności, samo umieszczenie nawiasów wokół podwyrażenia sprawia, że którykolwiek z powyższych (a) jest ważny, a (b) przypisanie. Na przykład, następujące wykonuje przypisanie:
median((x = 1 : 10))
Ale także:
if (! (nf = length(from))) return()
teraz możesz sprzeciwić się temu, że taki kod jest okropny (i możesz mieć rację). Ale wziąłem ten kod z funkcji base::file.copy
(zastępując <-
na =
) - to wszechobecny wzorzec w dużej części podstawowej bazy kodowej R.
[
=
przypisanie jest dozwolone tylko w dwóch miejscach gramatyki: na najwyższym poziomie (jako kompletny program lub wyrażenie wpisane przez użytkownika); a gdy jest odizolowane od otaczającej struktury logicznej, za pomocą nawiasów lub dodatkowej pary nawiasów.
W sumie przez domyślnie operatory <-
i =
robią to samo. Ale każdy z nich może byćprzesłonięty oddzielnie, aby zmienić jego zachowanie. Dla kontrastu, <-
i ->
(przypisanie od lewej do prawej), choć składniowo różne, zawsze wywołują tę samą funkcję. Nadpisywanie jedno również nadpisuje drugie. Wiedza o tym jest rzadko praktyczna , ale może być używana do zabawnych żartów .
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
2021-01-21 14:07:26
Różnica w operatorach przypisania jest wyraźniejsza, gdy używa się ich do ustawiania wartości argumentu w wywołaniu funkcji. Na przykład:
median(x = 1:10)
x
## Error: object 'x' not found
W tym przypadku, x
jest zadeklarowana w zakresie funkcji, więc nie istnieje w przestrzeni roboczej użytkownika.
median(x <- 1:10)
x
## [1] 1 2 3 4 5 6 7 8 9 10
W tym przypadku {[8] } jest zadeklarowana w przestrzeni roboczej użytkownika, więc można jej użyć po zakończeniu wywołania funkcji.
Istnieje ogólna preferencja wśród społeczności R do korzystania <-
do przypisania (innych niż w podpisach funkcji) dla zgodności z (bardzo) starymi wersjami S-Plus. Zauważ, że spacje pomagają wyjaśnić sytuacje takie jak
x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3
Większość Idów R ma skróty klawiaturowe, które ułatwiają pisanie <-
. Ctrl + = in Architect, Alt + - in RStudio (Option + - pod macOS), Shift + - (podkreślenie) w emacs+ESS.
Jeśli wolisz pisząc =
do <-
ale chcesz użyć bardziej popularnego symbolu przypisania dla publicznie udostępnionego kodu( np. na CRAN), wtedy możesz użyć jednego z tidy_*
funkcje w pakiecie formatR
do automatycznego zastąpienia =
przez <-
.
library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5
Odpowiedź na pytanie " dlaczego x <- y = 5
rzuca błąd, ale nie x <- y <- 5
?"to" wszystko zależy od magii zawartej w parserze". Składnia R zawiera wiele niejednoznacznych przypadków , które muszą być rozwiązane w jeden sposób lub kolejny. Parser wybiera rozwiązanie bitów wyrażenia w różnych porządkach w zależności od tego, czy użyto =
lub <-
.
Aby zrozumieć, co się dzieje, musisz wiedzieć, że przypisanie po cichu Zwraca wartość, która została przypisana. Można to zobaczyć wyraźniej poprzez wyraźne drukowanie, na przykład print(x <- 2 + 3)
.
Po drugie, jest jaśniejsze, jeśli używamy zapisu przedrostkowego do przypisania. Więc
x <- 5
`<-`(x, 5) #same thing
y = 5
`=`(y, 5) #also the same thing
Parser interpretuje x <- y <- 5
jako
`<-`(x, `<-`(y, 5))
We można się spodziewać, że x <- y = 5
będzie wtedy
`<-`(x, `=`(y, 5))
Ale w rzeczywistości jest interpretowany jako
`=`(`<-`(x, y), 5)
Wynika to z faktu, że =
ma niższy priorytet niż <-
, Jak pokazano na ?Syntax
Strona pomocy.
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-08 15:38:42
Google 'S R style guide upraszcza problem, zakazując" = " do przypisania. Niezły wybór.
Https://google.github.io/styleguide/Rguide.xml
Podręcznik R zawiera szczegółowe informacje na temat wszystkich 5 operatorów przydziałów.
Http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html
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-06-06 11:08:21
x = y = 5
jest równoważne x = (y = 5)
, ponieważ operatory przypisania "grupują" od prawej do lewej, co działa. Znaczenie: Przypisz 5 do y
, pozostawiając liczbę 5; a następnie przypisz 5 do x
.
To nie to samo co (x = y) = 5
, co nie działa! Znaczenie: przypisać wartość y
do x
, pozostawiając wartość y
; a następnie przypisać 5 do, umm... co dokładnie?
Kiedy miesza się różne rodzaje operatorów przyporządkowania, <-
wiąże się mocniej niż =
. Więc x = y <- 5
jest interpretowane jako x = (y <- 5)
, co ma sens.
Niestety, x <- y = 5
jest interpretowane jako (x <- y) = 5
, co nie działa!
Zobacz ?Syntax
i ?assignOps
dla zasad pierwszeństwa (wiążących) i grupowania.
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-09 14:55:40
Według Johna Chambersa, operator =
jest dozwolony tylko na "najwyższym poziomie", co oznacza, że nie jest dozwolony w strukturach sterowania, takich jak if
, co czyni poniższy błąd programowania nielegalnym.
> if(x = 0) 1 else x
Error: syntax error
Jak pisze, " wyłączenie nowej formy przypisania [ = ] w wyrażeniach sterujących pozwala uniknąć błędów programistycznych (takich jak powyższy przykład), które są bardziej prawdopodobne w przypadku operatora równego niż w przypadku innych przypisań S."
Można to zrobić, jeśli jest " odizolowany od otacza strukturę logiczną, nawiasami lub dodatkową parą nawiasów", więc if ((x = 0)) 1 else x
zadziałałoby.
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-03-02 16:50:57
Operatory <-
i =
przypisują do środowiska, w którym są oceniane. Operator <-
może być używany wszędzie, natomiast operator =
jest dozwolony tylko na najwyższym poziomie (np. w pełnym wyrażeniu wpisanym w wierszu polecenia) lub jako jeden z podwyrażeń w zwartej liście wyrażeń.
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-08 10:04:19
Może to również przyczynić się do zrozumienia różnicy między tymi dwoma operatorami:
df <- data.frame(
a = rnorm(10),
b <- rnorm(10)
)
Dla pierwszego elementu R ma przypisane wartości i nazwę właściwą, podczas gdy nazwa drugiego elementu wygląda trochę dziwnie.
str(df)
# 'data.frame': 10 obs. of 2 variables:
# $ a : num 0.6393 1.125 -1.2514 0.0729 -1.3292 ...
# $ b....rnorm.10.: num 0.2485 0.0391 -1.6532 -0.3366 1.1951 ...
R Wersja 3.3.2 (2016-10-31); macOS Sierra 10.12.1
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-01-31 17:11:23