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?
Author: smci, 2009-11-16

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):

  1. pierwsze znaczenie ma operator przypisania . To wszystko, o czym do tej pory rozmawialiśmy.
  2. 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.

W 2007 roku, w ramach projektu the R documentation, w ramach projektu the R documentation, stworzonego przez Johna Chambersa, stworzonego przez the R documentation of the R documentation, stworzonego przez The r documentation of the R documentation of the R documentation of the R documentation of the R documentation of the 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 .

 151
Author: Konrad Rudolph,
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.

 684
Author: Richie Cotton,
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

 106
Author: Nosredna,
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.

 40
Author: Steve Pitchers,
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.

Zobacz http://developer.r-project.org/equalAssign.html

 34
Author: Aaron left Stack Overflow,
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ń.

 27
Author: Haim Evgi,
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

 6
Author: Denis Rasulev,
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