Question Quelles sont les différences entre "=" et "<-" dans R?


Quelles sont les différences entre les opérateurs d'affectation = et <- dans 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?


540
2017-11-16 12:14


origine


Réponses:


La différence de opérateurs d'affectation est plus clair lorsque vous les utilisez pour définir une 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 la portée de la fonction, de sorte qu'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é dans l'espace de travail de l'utilisateur, vous pouvez donc l'utiliser une fois l'appel de fonction terminé.


Il y a une préférence générale parmi la communauté R pour l'utilisation <- pour l'affectation (autre que dans les signatures de fonction) pour la compatibilité avec les (très) anciennes versions de S-Plus. Notez que les espaces aident à clarifier des situations comme

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

La plupart des EDI R ont des raccourcis clavier pour faire <- plus facile à taper. Ctrl + = en architecte, Alt + - dans RStudio (Option + - sous macOS), Décalage + - (trait de soulignement) dans emacs + ESS.


Si vous préférez écrire = à <- mais vous voulez utiliser le symbole d'affectation plus commun pour le code publié publiquement (sur CRAN, par exemple), vous pouvez utiliser l'un des tidy_* fonctions dans le formatR paquet 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 lancer une erreur mais pas x <- y <- 5? "est" Cela dépend de la magie contenue dans l'analyseur ". La syntaxe de R contient de nombreux cas ambigus qui doivent être résolus d'une manière ou d'une autre. L'analyseur choisit de résoudre les bits de l'expression dans différents ordres selon que = ou <- a été utilisé.

Pour comprendre ce qui se passe, vous devez savoir que l'affectation renvoie silencieusement la valeur attribuée. Vous pouvez le voir plus clairement en imprimant explicitement, par exemple print(x <- 2 + 3).

Deuxièmement, il est plus clair si nous utilisons la notation de préfixe pour l'affectation. Alors

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

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

L'analyseur interprète x <- y <- 5 comme

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

Nous pourrions nous attendre à ce que x <- y = 5 serait alors

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

mais en fait, il est interprété comme

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

Ceci est dû au fait = est moins prioritaire que <-, comme indiqué sur le ?Syntax page d'aide


523
2017-11-16 14:36



Le guide de style R de Google simplifie le problème en interdisant le «=» pour l'attribution. Pas un mauvais choix.

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

Le manuel R va dans le détail sur les 5 opérateurs d'affectation.

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


87
2017-11-16 14:44



Selon John Chambers, l'opérateur = est seulement autorisé au «niveau supérieur», ce qui signifie qu'il n'est pas autorisé dans les structures de contrôle comme if, rendant l'erreur de programmation suivante illégale.

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

Comme il l'écrit, "Refuser la nouvelle forme d'affectation [=] dans les expressions de contrôle évite les erreurs de programmation (comme l'exemple ci-dessus) qui sont plus probables avec l'opérateur égal qu'avec les autres assignations S."

Vous pouvez réussir à faire cela s'il est "isolé de la structure logique environnante, par des accolades ou une paire de parenthèses supplémentaire". if ((x = 0)) 1 else x travaillerait.

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


28
2018-01-28 18:34



x = y = 5 est équivalent à x = (y = 5), parce que les opérateurs d'attribution "groupe" droite à gauche, ce qui fonctionne. Signification: assigner 5 à y, laissant le numéro 5; puis attribuer ce 5 à x.

Ce n'est pas la même chose que (x = y) = 5, ça ne marche pas! Signification: attribuer la valeur de y à x, laissant la valeur de y; et puis assigner 5 à, umm ..., quoi exactement?

Lorsque vous mélangez les différents types d'opérateurs d'affectation, <- lie plus serré que =. Alors x = y <- 5 est interprété comme x = (y <- 5), ce qui est le cas qui a du 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 les règles de priorité et de regroupement.


26
2017-09-09 21:21



Les opérateurs <- et = affecter dans l'environnement dans lequel ils sont évalués. L'opérateur <- peut être utilisé n'importe où, alors que l'opérateur = est seulement autorisé au plus haut niveau (par exemple, dans l'expression complète tapée à l'invite de commande) ou en tant qu'une des sous-expressions dans une liste d'expressions contreventée.


20
2017-11-16 12:21



Quelles sont les différences entre les opérateurs d'affectation = et <- dans R?

Comme le montre votre exemple, = et <- avoir une priorité d'opérateur légèrement différente (qui détermine l'ordre d'évaluation lorsqu'ils sont mélangés dans la même expression). En réalité, ?Syntax dans R donne la table de priorité d'opérateur suivante, 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 des questions sur opérateurs d'affectation: oui, c'est la seule différence. Cependant, vous seriez pardonné de croire le contraire. Même la documentation R de ?assignOps affirme qu'il y a plus de différences:

L'opérateur <- peut être utilisé n'importe où,   alors que l'opérateur = n'est autorisé qu'au niveau supérieur (par exemple,   dans l'expression complète tapée à l'invite de commande) ou en tant qu'un   des sous-expressions dans une liste d'expressions contreventée.

Ne mettons pas trop un point dessus: la documentation R est (subtilement) fausse  [1]. C'est facile à montrer: il suffit de trouver un contre-exemple de = opérateur qui n'est pas (a) au niveau supérieur, ni (b) une sous-expression dans une liste d'expressions contreventée (c.-à-d. {…; …}). - Sans plus tarder:

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

De toute évidence, nous avons effectué une mission, en utilisant =, en dehors des contextes (a) et (b). Alors, pourquoi la documentation d'une caractéristique de base du langage R est-elle erronée depuis des décennies?

C'est parce que dans la syntaxe de R le symbole = a deux significations distinctes qui sont systématiquement confondues:

  1. Le premier sens est en tant que opérateur d'assignation. C'est tout ce dont nous avons parlé jusqu'à présent.
  2. Le second sens n'est pas un opérateur mais plutôt un jeton de syntaxe que les signaux argument nommé passant dans un appel de fonction. Contrairement à la = opérateur il n'effectue aucune action à l'exécution, il change simplement la façon dont une expression est analysée.

Voyons voir.

Dans tout morceau de code de la forme générale ...

<Nom_fonction>(<Argname> = <valeur>, …)
<Nom_fonction>(<Args>, <Argname> = <valeur>, …)

… la = est le jeton qui définit le passage d'argument nommé: il est ne pas l'opérateur d'affectation. En outre, = est entièrement interdit dans certains contextes syntaxiques:

if (<Var> = <valeur>) …
while (<Var> = <valeur>) …
for (<Var> = <valeur> in <Value2>) …
for (<Var1> in <Var2> = <valeur>) …

N'importe lequel de ceux-ci déclenchera une erreur "unexpected '=' in <bla>".

Dans tout autre contexte, = se réfère à l'appel de l'opérateur d'affectation. En particulier, le simple fait de placer des parenthèses autour de la sous-expression rend l'un des éléments ci-dessus (a) valide, et (b) un affectation. Par exemple, ce qui suit effectue l'affectation:

median((x = 1 : 10))

Mais aussi:

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

Maintenant, vous pourriez objecter qu'un tel code est atroce (et vous avez peut-être raison). Mais j'ai pris ce code de la base::file.copy fonction (remplaçant <- avec =) - c'est un modèle omniprésent dans une grande partie du code R de base.

le explication originale par John Chambers, sur lequel la documentation de R est probablement basée, explique réellement ceci correctement:

[= l'assignation est] permise seulement dans deux endroits de la grammaire: au niveau supérieur (comme un programme complet ou une expression typée par l'utilisateur); et lorsqu'il est isolé de la structure logique environnante, par des accolades ou une paire de parenthèses supplémentaire.


Une confession: j'ai menti plus tôt. Là est une différence supplémentaire entre le = et <- opérateurs: ils appellent des fonctions distinctes. Par défaut, ces fonctions font la même chose mais vous pouvez les remplacer séparément pour changer le comportement. Par contre, <- et -> (affectation de gauche à droite), bien que syntaxiquement distincte, appelle toujours le même fonction. Le remplacement d'un remplacera également l'autre. Sachant cela est rarement pratique mais ça pouvez être utilisé pour quelques amusantes manigances.


12
2017-07-27 19:17



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 assigné des valeurs et un 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 ...

R version 3.3.2 (2016-10-31); macOS Sierra 10.12.1


4
2017-12-10 21:32