Quelles sont les différences entre « = » et « <- » opérateurs d'affectation en R?
-
20-09-2019 - |
Question
Quelles sont les différences entre les opérateurs d'affectation =
et <-
en R?
Je sais que les opérateurs sont légèrement différents, comme le montre cet exemple
x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"
Mais est-ce la seule différence?
La solution
Quelles sont les différences entre les opérateurs d'affectation
=
et<-
en R?
En tant que votre exemple montre, =
et <-
ont opérateur légèrement différente priorité (qui détermine l'ordre d'évaluation quand ils sont mélangés dans la même expression). En fait, ?Syntax
R donne la priorité de l'opérateur suivant table, du plus haut au plus bas:
… ‘-> ->>’ rightwards assignment ‘<- <<-’ assignment (right to left) ‘=’ assignment (right to left) …
Mais est-ce la seule différence?
Puisque vous posiez sur les opérateurs d'affectation : oui, c'est la seule différence. Cependant, vous seriez pardonné de croire le contraire. Même la documentation R ?assignOps
affirme qu'il ya plus différences:
Le
<-
opérateur peut être utilisé partout, tandis que le=
de l'opérateur est autorisé uniquement au niveau supérieur (par exemple, dans l'expression complète tapé à l'invite de commande) ou un des sous-expressions dans une liste contreventement des expressions.
Il ne faut pas mettre trop insister là-dessus: la documentation R est (subtilement) mal [ 1 ] . Cela est facile à montrer: nous avons juste besoin de trouver un contre-exemple de l'opérateur =
qui n'est pas (a) au niveau supérieur, ni (b) une sous-expression dans une liste contreventement des expressions (à savoir {…; …}
). - Sans plus tarder:
x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1
Il est clair que nous avons effectué une mission, en utilisant =
, en dehors des contextes (a) et (b). Alors, pourquoi la documentation d'une fonctionnalité de langage R core eu tort pendant des décennies?
Il est parce que dans la syntaxe de R le =
symbole a deux significations distinctes qui reçoivent systématiquement: confondait
- Le premier sens est comme un opérateur d'affectation . C'est tout ce que nous avons parlé jusqu'à présent.
- La deuxième signification est pas un opérateur mais plutôt un jeton de syntaxe que les signaux argument nommé passant dans un appel de fonction. Contrairement à l'opérateur
=
il effectue aucune action lors de l'exécution, il change simplement la façon dont une expression est analysée.
Voyons voir.
En tout morceau de code de la forme générale ...
‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)
... =
est le jeton qui définit argument nommé qui passe: il est pas l'opérateur d'affectation. De plus, =
est tout à fait interdit dans certains contextes syntaxiques:
if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …
Tous ces éléments vont générer une erreur « inattendu '=' dans
Dans tout autre contexte, =
fait référence à l'appel de l'opérateur d'affectation. En particulier, en mettant entre parenthèses simplement autour de la sous-expression fait tout de ce qui précède (a) valide, et (b) une affectation . Par exemple, ce qui suit effectue la cession:
median((x = 1 : 10))
Mais aussi:
if (! (nf = length(from))) return()
Maintenant, vous pourriez objecter que tel code est atroce (et vous pouvez être à droite). Je pris le code de la fonction de base::file.copy
(remplaçant <-
avec =
) -. Il est un motif omniprésent dans une grande partie du noyau R codebase
originale par John Chambers qui la la documentation R est probablement basée sur , explique en fait cela correctement:
[affectation de
=
est] admis dans deux endroits dans la grammaire: au niveau supérieur (comme un programme complet ou l'expression tapé par l'utilisateur); et lorsqu'il est isolé à partir de stru logique environnantecture, par des entretoises ou une paire de parenthèses.
Une confession: je mentais plus tôt. Il une différence supplémentaire entre les opérateurs de =
et <-
: ils appellent des fonctions distinctes. Par défaut, ces fonctions font la même chose, mais vous pouvez remplacer l'un d'eux séparément pour modifier le comportement. En revanche, <-
et ->
(affectation de gauche à droite), bien que syntaxiquement distincte, toujours faire appel à la même fonction. Redéfinition remplace également l'un de l'autre. Sachant cela est rarement pratique mais peut être utilisés pour certains manigances fun .
Autres conseils
La différence dans les opérateurs d'affectation de est plus clair lorsque vous les utilisez pour définir une la valeur d'argument dans un appel de fonction. Par exemple:
median(x = 1:10)
x
## Error: object 'x' not found
Dans ce cas, x
est déclaré dans le cadre de la fonction, il n'existe pas dans l'espace de travail de l'utilisateur.
median(x <- 1:10)
x
## [1] 1 2 3 4 5 6 7 8 9 10
Dans ce cas, x
est déclarée dans l'espace de travail de l'utilisateur, de sorte que vous pouvez l'utiliser après l'appel de fonction est terminée.
Il y a une préférence générale au sein de la communauté R pour l'utilisation <-
pour l'attribution (autres que dans les signatures de fonction) pour la compatibilité avec les (très) anciennes versions de S-Plus. Notez que les espaces permettent de clarifier des situations comme
x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3
La plupart des R IDEs ont des raccourcis clavier pour rendre plus facile à taper <-
. Ctrl + = Architect, Alt + - dans rstudio ( Option + < KBD> - sous MacOS), Maj + -. (souligné) dans emacs + ESS
Si vous préférez écrire =
à <-
mais souhaitez utiliser le symbole d'affectation plus commune pour le code rendu public (le CRAN, par exemple), vous pouvez utiliser l'un des fonctions tidy_*
dans le package formatR
pour remplacer automatiquement =
avec <-
.
library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5
La réponse à la question « Pourquoi x <- y = 5
jeter une erreur, mais pas x <- y <- 5
? » est «C'est vers le bas à la magie contenue dans l'analyseur ». La syntaxe de R contient ?Syntax
page d'aide.
guide de style R Google simplifie la question en interdisant la cession pour « = ». Pas un mauvais choix.
https://google.github.io/styleguide/Rguide.xml
Le manuel R passe en détail agréable sur les 5 opérateurs d'affectation.
http: //stat.ethz. ch / R-manuel / R-patched / bibliothèque / base / html / assignOps.html
x = y = 5
est équivalent à x = (y = 5)
, parce que les opérateurs d'affectation « groupe » de droite à gauche, ce qui fonctionne. Signification: affecter 5 à y
, en laissant le numéro 5; puis attribuez-lui que 5 à x
.
Ce n'est pas la même chose que (x = y) = 5
, qui ne fonctionne pas! Signification: assigner la valeur de y
à x
, en laissant la valeur de y
; puis attribuez-lui 5 à, euh ..., qu'est-ce exactement?
Lorsque vous mélangez les différents types d'opérateurs d'affectation, <-
lie plus serré que =
. Donc x = y <- 5
est interprété comme x = (y <- 5)
, ce qui est le cas qui fait sens.
Malheureusement, x <- y = 5
est interprété comme (x <- y) = 5
, ce qui est le cas qui ne fonctionne pas!
Voir ?Syntax
et ?assignOps
pour la priorité (contraignante) et les règles de groupement.
Selon John Chambers, le =
opérateur est autorisé seulement à « niveau supérieur », ce qui signifie qu'il est interdit dans les structures de contrôle comme if
, ce qui rend l'erreur de programmation suivante illégale.
> if(x = 0) 1 else x
Error: syntax error
Comme il l'écrit, « refuse la nouvelle forme d'affectation [=] dans les expressions de contrôle évite les erreurs de programmation (comme l'exemple ci-dessus) qui sont plus susceptibles de l'opérateur égal qu'avec d'autres missions de. »
Vous parvenez à le faire si elle est « isolé de la structure logique entourant, par des accolades ou une paire de parenthèses, » si if ((x = 0)) 1 else x
fonctionnerait.
Les opérateurs <-
et =
dans l'environnement assignent dans lequel ils sont évalués. Le <-
opérateur peut être utilisé partout, alors que l'opérateur =
n'est autorisé au niveau supérieur (par exemple, dans l'expression complète tapé à l'invite de commande) ou comme l'un des les sous-expressions dans une liste contreventement des expressions.
Cela peut également ajouter à la compréhension de la différence entre ces deux opérateurs:
df <- data.frame(
a = rnorm(10),
b <- rnorm(10)
)
Pour le premier élément R a attribué des valeurs et nom propre, tandis que le nom du second élément semble un peu étrange.
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 ...
version R 3.3.2 (31/10/2016); macOS Sierra 10.12.1