Was sind die Unterschiede zwischen den Zuweisungsoperatoren =
und <-
in R?
Ich weiß, dass die Operatoren etwas anders sind, wie dieses Beispiel zeigt
x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"
Aber ist das der einzige Unterschied?
r
assignment-operator
r-faq
csgillespie
quelle
quelle
<-
Symbols von alten APL-Tastaturen, auf denen sich tatsächlich eine einzige<-
Taste befand.Antworten:
Als Ihr Beispiel zeigt,
=
und<-
etwas anderen Operator Vorrang hat (was die Reihenfolge der Auswertung bestimmt , wann sie in dem gleichen Ausdruck gemischt werden). Tatsächlich gibt?Syntax
in R die folgende Operator-Prioritätstabelle vom höchsten zum niedrigsten an:Aber ist das der einzige Unterschied?
Da Sie nach den Zuweisungsoperatoren gefragt haben : Ja, das ist der einzige Unterschied. Es wird Ihnen jedoch vergeben, wenn Sie etwas anderes glauben. Sogar die R-Dokumentation von
?assignOps
Behauptungen, dass es mehr Unterschiede gibt:Lassen Sie uns nicht zu genau darauf eingehen: Die R-Dokumentation ist (subtil) falsch [ 1 ] . Dies ist leicht zu zeigen: Wir müssen nur ein Gegenbeispiel für den
=
Operator finden, das sich nicht (a) auf der obersten Ebene befindet, noch (b) einen Unterausdruck in einer geschweiften Liste von Ausdrücken (dh{…; …}
). - Ohne weiteres:Natürlich haben wir eine Aufgabe
=
außerhalb der Kontexte (a) und (b) durchgeführt. Warum ist die Dokumentation eines Kernmerkmals der R-Sprache seit Jahrzehnten falsch?=
Dies liegt daran, dass das Symbol in Rs Syntax zwei unterschiedliche Bedeutungen hat, die routinemäßig zusammengeführt werden:=
Operator, der zur Laufzeit keine Aktion ausführt, ändert er lediglich die Art und Weise, wie ein Ausdruck analysiert wird.Wir werden sehen.
In jedem Code der allgemeinen Form…
… Das
=
ist das Token, das die Übergabe benannter Argumente definiert: Es ist nicht der Zuweisungsoperator. Darüber hinaus=
ist in einigen syntaktischen Kontexten völlig verboten :Jedes dieser Ereignisse löst den Fehler "unerwartet '=' in ‹bla›" aus.
=
Bezieht sich in jedem anderen Kontext auf den Aufruf des Zuweisungsoperators. Insbesondere das bloße Setzen von Klammern um den Unterausdruck macht eine der oben genannten (a) und (b) eine Zuweisung gültig . Zum Beispiel führt das Folgende eine Zuweisung durch:Aber auch:
Jetzt könnten Sie einwenden, dass ein solcher Code grausam ist (und Sie könnten Recht haben). Aber ich nahm diesen Code aus der
base::file.copy
Funktion (ersetzt<-
mit=
) - es ist ein durchdringendes Muster in weiten Teilen der Kern R - Codebasis.Die ursprüngliche Erklärung von John Chambers , auf der die R-Dokumentation wahrscheinlich basiert, erklärt dies tatsächlich richtig:
Ein Geständnis: Ich habe früher gelogen. Es gibt einen zusätzlichen Unterschied zwischen den Operatoren
=
und<-
: Sie rufen unterschiedliche Funktionen auf. Standardmäßig machen diese Funktionen dasselbe, aber Sie können beide separat überschreiben, um das Verhalten zu ändern. Im Gegensatz dazu rufen<-
und->
(Zuordnung von links nach rechts), obwohl syntaktisch unterschiedlich, immer dieselbe Funktion auf. Das Überschreiben eines überschreibt auch das andere. Das zu wissen ist selten praktisch , kann aber für ein paar lustige Spielereien verwendet werden .quelle
?
tatsächlich zwischen=
und<-
, was wichtige Konsequenzen beim Überschreiben hat?
, und praktisch keine anderen.main/gram.y
) ist die Priorität von?
korrekt dokumentiert und niedriger als beide=
und<-
.=
Sie eine Sonderbehandlung erhalten, bevor der Analysebaum erstellt wird. Möglicherweise im Zusammenhang mit Funktionsargumenten ist es sinnvoll, nach dem Rest des Ausdrucks zufoo(x = a ? b)
suchen,=
bevor wir ihn analysieren.Der Unterschied zwischen Zuweisungsoperatoren wird deutlicher, wenn Sie sie zum Festlegen eines Argumentwerts in einem Funktionsaufruf verwenden. Zum Beispiel:
In diesem Fall
x
wird im Rahmen der Funktion deklariert, sodass sie im Benutzerarbeitsbereich nicht vorhanden ist.In diesem Fall
x
wird im Benutzerarbeitsbereich deklariert, sodass Sie ihn nach Abschluss des Funktionsaufrufs verwenden können.In der R-Community wird die
<-
Kompatibilität mit (sehr) alten Versionen von S-Plus generell für die Zuweisung (außer für Funktionssignaturen) bevorzugt . Beachten Sie, dass die Leerzeichen helfen, Situationen wie zu klärenDie meisten R-IDEs verfügen über Tastaturkürzel, um die Eingabe zu
<-
vereinfachen. Ctrl+ =in Architect, Alt+ -in RStudio ( Option+ -unter macOS), Shift+ -(Unterstrich) in emacs + ESS.Wenn Sie mit dem Schreiben vorziehen
=
zu<-
wollen aber für öffentlich veröffentlichten Code (auf CRAN, zum Beispiel) , das häufigen Zuordnung Symbol verwenden, dann können Sie eine der Verwendungtidy_*
Funktionen imformatR
Paket automatisch zu ersetzen=
mit<-
.Die Antwort auf die Frage "Warum
x <- y = 5
wirft ein Fehler aber nichtx <- y <- 5
?" ist "Es liegt an der Magie, die im Parser enthalten ist". Die Syntax von R enthält viele mehrdeutige Fälle , die auf die eine oder andere Weise gelöst werden müssen. Der Parser entscheidet sich dafür, die Bits des Ausdrucks in unterschiedlicher Reihenfolge aufzulösen, je nachdem, ob=
oder<-
nicht.Um zu verstehen, was passiert, müssen Sie wissen, dass die Zuweisung den zugewiesenen Wert stillschweigend zurückgibt. Sie können dies deutlicher erkennen, indem Sie beispielsweise explizit drucken
print(x <- 2 + 3)
.Zweitens ist es klarer, wenn wir die Präfixnotation für die Zuweisung verwenden. Damit
Der Parser interpretiert
x <- y <- 5
alsMan könnte erwarten , dass
x <- y = 5
wäre dannaber eigentlich wird es interpretiert als
Dies liegt daran, dass die
=
Priorität niedriger<-
ist als auf der?Syntax
Hilfeseite angegeben.quelle
median((x = 1:10))
jedoch den gleichen Effekt wiemedian(x <- 1:10)
.x <- x = 5
interpretiert wird, etwas falsch ist: In Wirklichkeit interpretiert R sie als`<-<-`(x, y = 5, value = 5)
(was selbst mehr oder weniger gleichwertig isttmp <- x; x <- `<-<-`(tmp, y = 5, value = 5)
). Huch!=
in einem Funktionsaufruf verwenden, führt keine Zuweisung durch und ist kein Zuweisungsoperator. Es ist ein völlig unterschiedlicher analysierter R-Ausdruck, der zufällig dasselbe Zeichen verwendet. Außerdem wird der von Ihnen angezeigte Codex
im Funktionsumfang nicht "deklariert" . Die Funktionsdeklaration führt diese Deklaration aus. Der Funktionsaufruf funktioniert nicht (mit benannten...
Argumenten wird es etwas komplizierter ).Der R-Styleguide von Google vereinfacht das Problem, indem das "=" für die Zuweisung gesperrt wird. Keine schlechte Wahl.
https://google.github.io/styleguide/Rguide.xml
Das R-Handbuch geht detailliert auf alle 5 Zuweisungsoperatoren ein.
http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html
quelle
x<-y
wannx < -y
gemeint war, ärgert mich so sehr, dass ich es persönlich vorziehe=
. Es scheint mir nicht gut zu sein, wenn Ihr Code davon abhängt, dass Leerzeichen vorhanden sind. Es ist in Ordnung, Abstände als Stilempfehlung vorzuschlagen, aber damit Ihr Code anders ausgeführt wird, unabhängig davon, ob ein Leerzeichen vorhanden ist oder nicht. Was passiert, wenn Sie Ihren Code neu formatieren oder Suchen und Ersetzen verwenden, kann das Leerzeichen manchmal verschwinden und der Code geht schief. Das ist kein Problem mit=
. IIUC, Verbot bedeutet=
, "<-
" zu verlangen ; dh 3 Zeichen einschließlich eines Leerzeichens, nicht nur "<-
".TRUE
von R berücksichtigt wird. Wenn Sie also testen möchten, obx
es kleiner als ist-y
, schreiben Sie möglicherweise,if (x<-y)
was nicht warnt oder fehlerhaft ist und anscheinend einwandfrei funktioniert. Es wird nur sein ,FALSE
wenny=0
, wenn.=
und verwenden,<-
ist es schwer zu argumentieren, dass ein zusätzlicher Schritt vongrep "[^<]<-[^ ]" *.R
nicht erforderlich ist.=
braucht so einen nichtgrep
.<-
wenn Sie verwenden können=
? In 99,99% der Fälle=
ist in Ordnung. Manchmal braucht man<<-
aber, was eine andere Geschichte ist.x = y = 5
ist äquivalent zux = (y = 5)
, weil die Zuweisungsoperatoren von rechts nach links "gruppieren", was funktioniert. Bedeutung: Weisen Sie 5 zuy
und lassen Sie die Nummer 5; und dann diese 5 zuweisenx
.Dies ist nicht dasselbe wie
(x = y) = 5
, was nicht funktioniert! Bedeutung: Weisen Sie den Wert vony
bis zux
und lassen Sie den Wert vony
; und dann 5 zuweisen, umm ..., was genau?Wenn Sie die verschiedenen Arten von Zuweisungsoperatoren mischen, werden die
<-
Bindungen enger als=
. Sox = y <- 5
wird interpretiertx = (y <- 5)
, was sinnvoll ist.Wird leider
x <- y = 5
als interpretiert(x <- y) = 5
, was der Fall ist, der nicht funktioniert!Siehe
?Syntax
und?assignOps
für die Vorrang- (Bindungs-) und Gruppierungsregeln.quelle
<- <<-
steht oben=
in<-
der Rangliste , was bedeutet , dass zuerst ausgeführt wird. Alsox <- y = 5
sollte ausgeführt werden als(x <- y) = 5
.Laut John Chambers ist der Bediener
=
nur auf "der obersten Ebene" erlaubt, was bedeutet, dass er in Kontrollstrukturen wie nicht erlaubt istif
, was den folgenden Programmierfehler illegal macht.Wie er schreibt: "Wenn Sie das neue Zuweisungsformular [=] in Steuerausdrücken nicht zulassen, werden Programmierfehler (wie im obigen Beispiel) vermieden, die beim gleichen Operator wahrscheinlicher sind als bei anderen S-Zuweisungen."
Sie können dies tun, wenn es "durch Klammern oder ein zusätzliches Klammerpaar von der umgebenden logischen Struktur isoliert" ist
if ((x = 0)) 1 else x
.Siehe http://developer.r-project.org/equalAssign.html
quelle
x==0
fast immer gemeint ist.x=0
als Aufgabe zu seinx<-0
!=
so wenig wie möglich zu verwenden, weil=
und==
so ähnlich aussehen.if(x = 0) 1 else x
löst einen Fehler aus und hilft mir, einen Fehler zu finden und zu korrigieren.if(x <- 1) 1 else x
wirft keinen Fehler und ist sehr verwirrend.else
Wert zurückgibt, wollten Sie ihn so schreiben?", Aber das könnte ein Wunschtraum sein ...Die Operatoren
<-
und=
ordnen der Umgebung zu, in der sie ausgewertet werden. Der Operator<-
kann überall verwendet werden, während der Operator=
nur auf der obersten Ebene (z. B. in dem an der Eingabeaufforderung eingegebenen vollständigen Ausdruck) oder als einer der Unterausdrücke in einer geschweiften Liste von Ausdrücken zulässig ist .quelle
x <- 42
auf seine eigene ist eine Aussage; inif (x <- 42) {}
wäre es ein Ausdruck, und ist nicht gültig. Dies hat natürlich nichts damit zu tun, ob Sie sich in der globalen Umgebung befinden oder nicht.1 + (x = 2)
function() x = 1
,repeat x = 1
,if (TRUE) x = 1
....Dies kann auch zum Verständnis des Unterschieds zwischen diesen beiden Operatoren beitragen:
Für das erste Element hat R Werte und Eigennamen zugewiesen, während der Name des zweiten Elements etwas seltsam aussieht.
R Version 3.3.2 (31.10.2016); macOS Sierra 10.12.1
quelle
data.frame
versucht, den Namen der angegebenen Variablen als Namen des Elements immake.names("b <- rnorm(10)")
.