955 Stimmen

Was sind die Unterschiede zwischen den Zuweisungsoperatoren "=" und "<-" in R?

Was sind die Unterschiede zwischen den Zuweisungsoperatoren = y <- in R?

Ich weiß, dass die Operatoren leicht unterschiedlich 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?

68 Stimmen

Wie bereits erwähnt aquí die Ursprünge der <- Symbol stammt von alten APL-Tastaturen, die eigentlich nur ein <- Taste auf sie.

805voto

Richie Cotton Punkte 112708

Der Unterschied in Zuweisungsoperatoren wird deutlicher, wenn Sie sie verwenden, um einen Argumentwert in einem Funktionsaufruf zu setzen. Zum Beispiel:

median(x = 1:10)
x   
## Error: object 'x' not found

In diesem Fall, x wird im Anwendungsbereich der Funktion deklariert und existiert daher nicht im Benutzerarbeitsbereich.

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

In diesem Fall, x wird im Benutzerarbeitsbereich deklariert, so dass Sie sie nach Abschluss des Funktionsaufrufs verwenden können.


In der R-Gemeinschaft gibt es eine allgemeine Präferenz für die Verwendung von <- für Zuweisungen (außer in Funktionssignaturen) aus Gründen der Kompatibilität mit (sehr) alten Versionen von S-Plus. Beachten Sie, dass die Leerzeichen helfen, Situationen zu klären wie

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

Die meisten R-IDEs haben Tastenkombinationen, um die <- leichter zu tippen. Ctrl + = in Architekt, Alt + - in RStudio ( Option + - unter macOS), Shift + - (Unterstrich) in emacs+ESS.


Wenn Sie lieber schreiben = a <- verwenden, aber das gebräuchlichere Zuweisungssymbol für öffentlich freigegebenen Code (z.B. auf CRAN) verwenden möchten, dann können Sie eines der tidy_* Funktionen im formatR Paket automatisch ersetzen = mit <- .

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

Die Antwort auf die Frage "Warum ist x <- y = 5 einen Fehler auslösen, aber nicht x <- y <- 5 ?" ist "Es liegt an der Magie des Parsers". Die Syntax von R enthält viele zweideutige Fälle die auf die eine oder andere Weise geklärt werden müssen. Der Parser löst die Bits des Ausdrucks in unterschiedlicher Reihenfolge auf, je nachdem, ob = o <- verwendet wurde.

Um zu verstehen, was hier passiert, müssen Sie wissen, dass eine Zuweisung immer den Wert zurückgibt, der zugewiesen wurde. Sie können das deutlicher sehen, wenn Sie zum Beispiel explizit drucken print(x <- 2 + 3) .

Zweitens ist es klarer, wenn wir für die Zuweisung die Präfix-Notation verwenden. Also

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

Der Parser interpretiert x <- y <- 5 como

`<-`(x, `<-`(y, 5))

Wir könnten erwarten, dass x <- y = 5 wäre dann

`<-`(x, `=`(y, 5))

aber eigentlich wird es interpretiert als

`=`(`<-`(x, y), 5)

Der Grund dafür ist = hat einen niedrigeren Vorrang als <- wie in der Tabelle ?Syntax Hilfeseite.

264voto

Konrad Rudolph Punkte 503837

Was sind die Unterschiede zwischen den Zuweisungsoperatoren = y <- in R?

Wie Ihr Beispiel zeigt, = y <- haben einen leicht unterschiedlichen Vorrang der Operatoren (was die Reihenfolge der Auswertung bestimmt, wenn sie im selben Ausdruck gemischt werden). In der Tat, ?Syntax in R ergibt die folgende Tabelle mit der Rangfolge der Operatoren, vom höchsten zum niedrigsten:

…
‘-> ->>’           rightwards assignment
‘<- <<-’           assignment (right to left)
‘=’                assignment (right to left)
…

Aber ist das der einzige Unterschied?

Da Sie sich nach dem Zuweisungsoperatoren : Ja, das ist der einzige Unterschied. Es wäre jedoch verzeihlich, wenn Sie etwas anderes glaubten. Sogar die R-Dokumentation von ?assignOps behauptet, dass es weitere Unterschiede gibt:

Der Betreiber <- kann überall verwendet werden, während der Operator = ist nur auf der obersten Ebene erlaubt (z.B., in dem vollständigen Ausdruck, der an der Eingabeaufforderung eingegeben wird) oder als einer der der Unterausdrücke in einer geschweiften Liste von Ausdrücken.

Wir wollen es nicht zu sehr auf die Spitze treiben: die R-Dokumentation ist falsch . Dies ist leicht zu zeigen: Wir müssen nur ein Gegenbeispiel für die = Operator, der weder (a) auf der obersten Ebene noch (b) ein Unterausdruck in einer geschweiften Liste von Ausdrücken ist (d. h. {…; …} ). - Ohne weitere Umschweife:

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

Offensichtlich haben wir eine Zuweisung durchgeführt, indem wir = außerhalb der Kontexte (a) und (b). Warum also ist die Dokumentation einer Kernfunktion der Sprache R seit Jahrzehnten falsch?

Das liegt daran, dass in der Syntax von R das Symbol = hat zwei unterschiedliche Bedeutungen, die routinemäßig verwechselt werden (selbst von Experten, auch in der oben zitierten Dokumentation):

  1. Die erste Bedeutung ist die eines Zuweisungsoperator . Das ist alles, worüber wir bis jetzt gesprochen haben.
  2. Die zweite Bedeutung ist nicht ein Operator, sondern ein Syntax-Token die Signale Übergabe von benannten Argumenten in einem Funktionsaufruf. Anders als die = Betreiber er führt keine Aktion zur Laufzeit aus, sondern ändert lediglich die Art und Weise, wie ein Ausdruck geparst wird.

Wie entscheidet R also, ob eine bestimmte Verwendung von = sich auf den Operator oder auf die Übergabe von benannten Argumenten bezieht? Schauen wir mal.

In jedem Stück Code der allgemeinen Form

‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)

die = ist das Token, das die Übergabe von benannten Argumenten definiert: Es ist no der Zuweisungsoperator. Außerdem, = ist vollständig Verbotene in einigen syntaktischen Kontexten:

if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …

Jede dieser Möglichkeiten führt zu einem Fehler "unerwartetes '=' in 'bla'".

In jedem anderen Zusammenhang, = bezieht sich auf den Aufruf des Zuweisungsoperators. Insbesondere macht das bloße Setzen von Klammern um den Unterausdruck jeden der oben genannten (a) gültig und (b) einen Auftrag . Zum Beispiel führt die folgende Zuordnung:

median((x = 1 : 10))

Aber auch:

if (! (nf = length(from))) return()

Nun könnten Sie einwenden, dass ein solcher Code grässlich ist (und Sie mögen Recht haben). Aber ich habe diesen Code aus der <code>base::file.copy</code> Funktion (anstelle von <code><-</code> mit <code>=</code> ) - es ist ein allgegenwärtiges Muster in einem Großteil der R-Kern-Codebasis.

El Originalerklärung von John Chambers , auf dem die R-Dokumentation wahrscheinlich basiert, erklärt dies eigentlich korrekt:

[ = Zuweisung ist] nur an zwei Stellen in der Grammatik erlaubt: auf der obersten Ebene (als vollständiges Programm oder benutzertypisierter Ausdruck); und wenn sie von der umgebenden logischen Struktur isoliert ist, durch geschweifte Klammern oder ein zusätzliches Paar Klammern.


Zusammenfassend lässt sich sagen, dass die Betreiber standardmäßig <- y = das Gleiche tun. Aber jeder von ihnen kann sein außer Kraft gesetzt getrennt, um sein Verhalten zu ändern. Im Gegensatz dazu, <- y -> (Links-nach-Rechts-Zuweisung), obwohl syntaktisch unterschiedlich, rufen immer die même Funktion. Das Überschreiben einer Funktion setzt auch die andere außer Kraft. Dies zu wissen, ist selten praktisch aber es peut für einige lustige Spielereien verwendet werden .

112voto

Nosredna Punkte 78203

Der R-Style-Guide von Google vereinfacht das Problem, indem er das "=" für Zuweisungen verbietet. Keine schlechte Wahl.

https://google.github.io/styleguide/Rguide.xml

Das R-Handbuch geht ausführlich auf alle 5 Zuweisungsoperatoren ein.

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html

52voto

Steve Pitchers Punkte 6701

x = y = 5 ist gleichbedeutend mit x = (y = 5) weil die Zuweisungsoperatoren von rechts nach links "gruppieren", was funktioniert. Das bedeutet: Zuweisung von 5 an y , wobei die Zahl 5 übrig bleibt, und weisen Sie dann diese 5 der x .

Dies ist nicht dasselbe wie (x = y) = 5 was nicht funktioniert! Bedeutung: Weisen Sie den Wert von y a x und lässt den Wert von y ; und dann 5 zuweisen, ähm..., was genau?

Wenn Sie die verschiedenen Arten von Zuweisungsoperatoren mischen, <- bindet fester als = . Also x = y <- 5 wird interpretiert als x = (y <- 5) Das ist der Fall, der Sinn macht.

Leider, x <- y = 5 wird interpretiert als (x <- y) = 5 das ist der Fall, der nicht funktioniert!

Voir ?Syntax y ?assignOps für die Vorrangregeln (Bindung) und Gruppierungsregeln.

39voto

Nach Angaben von John Chambers, dem Betreiber = ist nur auf "oberster Ebene" erlaubt, d.h. es ist nicht in Kontrollstrukturen wie if , wodurch der folgende Programmierfehler unzulässig wird.

> if(x = 0) 1 else x
Error: syntax error

Er schreibt: "Das Verbot der neuen Zuweisungsform [=] in Kontrollausdrücken vermeidet Programmierfehler (wie das obige Beispiel), die mit dem Gleichheitsoperator wahrscheinlicher sind als mit anderen S-Zuweisungen."

Dies ist möglich, wenn er "von der umgebenden logischen Struktur durch geschweifte Klammern oder ein zusätzliches Klammerpaar isoliert ist", also if ((x = 0)) 1 else x funktionieren würde.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X