2009-11-16 16 views
488

¿Cuáles son las diferencias entre los operadores de asignación = y <- en R?¿Cuáles son las diferencias entre "=" y "<-" en R?

Sé que los operadores son ligeramente diferentes, como muestra este ejemplo

x <- y <- 5 
x = y = 5 
x = y <- 5 
x <- y = 5 
# Error in (x <- y) = 5 : could not find function "<-<-" 

Pero es esta la única diferencia?

+22

Como se indicó [aquí] (http://blog.revolutionanalytics.com/2008/12/use-equals-or-arrow-for-assignment.html) los orígenes del '<-' el símbolo proviene de los viejos teclados APL que en realidad tenían una sola tecla '<-' en ellos. – joran

Respuesta

481

La diferencia en assignment operators es más clara cuando las usa para establecer un valor de argumento en una llamada de función. Por ejemplo:

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

En este caso, x se declara dentro del alcance de la función, por lo que no existe en el espacio de trabajo del usuario.

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

En este caso, x se declara en el espacio de trabajo del usuario, para que pueda usarlo después de la llamada a la función se ha completado.


Hay una preferencia general entre la comunidad de R para el uso de <- para la asignación (aparte de en las firmas de función) para la compatibilidad con (muy) viejas versiones de S-Plus. Tenga en cuenta que los espacios ayudan a aclarar situaciones como

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

más R IDE tienen atajos de teclado para hacer <- más fácil de escribir. Ctrl + = en Arquitecto, Alt + - en rstudio (Opción + - bajo MacOS), Shift + - (subrayado) en emacs + ESS.


Si prefiere escribir = a <- pero desea utilizar el símbolo de asignación más común para el código publicado públicamente (en CRAN, por ejemplo), entonces se puede utilizar una de las tidy_* funciones en el paquete formatR de forma automática reemplace = con <-.

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

La respuesta a la pregunta "¿Por qué x <- y = 5 Lanza un error, pero no x <- y <- 5?" es "depende de la magia contenida en el analizador". La sintaxis de R contiene many ambiguous cases que deben resolverse de una forma u otra.El analizador elige resolver los bits de la expresión en diferentes órdenes dependiendo de si se utilizó = o <-.

Para comprender lo que está sucediendo, debe saber que la asignación devuelve silenciosamente el valor asignado. Puede ver eso más claramente al imprimir explícitamente, por ejemplo print(x <- 2 + 3).

En segundo lugar, es más claro si usamos la notación de prefijo para la asignación. Así

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

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

El analizador interpreta como x <- y <- 5

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

Podríamos esperar que x <- y = 5 sería entonces

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

pero en realidad se pone interpretarse como

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

Esto se debe a que = tiene una prioridad menor que <-, como se muestra en la página de ayuda ?Syntax.

+1

Esto también se menciona en el capítulo 8.2.26 de [The R Inferno] (http://www.burns-stat.com/pages/Tutor/R_inferno.pdf) por Patrick Burns (No soy yo, sino una recomendación de todos modos) – Uwe

+1

Sin embargo, 'mediana ((x = 1:10))' tiene el mismo efecto que 'mediana (x <- 1:10) '. –

19

Los operadores <- y = se asignan al entorno en el que se evalúan. El operador <- se puede utilizar en cualquier lugar, mientras que el operador = sólo se permite en el nivel superior (por ejemplo, en la expresión completa tecleado en el símbolo) o como uno de los subexpresiones en una lista arriostradas de expresiones.

+8

Creo que "nivel superior" significa en el nivel de declaración, en lugar del nivel de expresión. Así que 'x <- 42' en sí mismo es una afirmación; en 'if (x <- 42) {}' sería una expresión, y no es válida. Para ser claros, esto no tiene nada que ver con si estás en el entorno global o no. –

+0

Esto: "el operador = solo está permitido en el nivel superior" es un malentendido generalizado y completamente erróneo. –

+0

Esto no es cierto; por ejemplo, esto funciona, aunque la asignación no es una expresión completa: '1 + (x = 2)' –

81

La guía de estilo R de Google simplifica la cuestión al prohibir el "=" para la asignación. No es una mala elección.

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

El manual R entra en el detalle agradable en los 5 operadores de asignación.

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

+96

La desventaja de la asignación accidental por 'x <-y 'cuando se quería decir' x <-y', me molesta tanto que personalmente prefiero '='. Tener mi código depende de que el espacio en blanco esté presente no me parece bien. Está bien sugerir el espaciado como consejo de estilo pero para que su código se ejecute de manera diferente, independientemente de si hay espacio o no. ¿Qué pasa si vuelves a formatear tu código, o usas buscar y reemplazar, el espacio en blanco a veces puede desaparecer y el código sale mal? Eso no es un problema con '='. IIUC, que prohíbe '=' equivale a requerir "' <- '"; es decir, 3 caracteres incluyendo un espacio, no solo "' <-' ". –

+9

Tenga en cuenta que cualquier no-0 se considera 'VERDADERO' por R. Entonces, si tiene la intención de probar si' x' es menor que '-y', puede escribir' if (x <-y) 'que no avisará o error, y parece que funciona bien. Sin embargo, solo será 'FALSE' cuando' y = 0'. –

+2

Si prohibes '=' y usas '<-', entonces es difícil argumentar que un paso extra de 'grep '[^ <] <- [^]" * .R' no es necesario. '=' no necesita un 'grep'. –

27

De acuerdo con John Chambers, el operador = sólo está permitido al "más alto nivel", lo que significa que no está permitido en las estructuras de control como if, haciendo ilegal el siguiente error de programación.

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

Como escribe, "No permitir la nueva forma de asignación [=] en expresiones de control evita errores de programación (tales como el ejemplo anterior) que son más probables con el operador igual que con otras asignaciones S".

Puede hacerlo si está "aislado de la estructura lógica circundante, con llaves o un par adicional de paréntesis", por lo que if ((x = 0)) 1 else x funcionaría.

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

+0

¿Qué esperas que haga esa línea? Sin duda, es equivalente a 'x = 0'? –

+11

Es un error común, 'x == 0' casi siempre se usa en su lugar. – Aaron

+12

Ah, sí, pasé por alto que dijiste "error de programación". En realidad, es una buena noticia que esto cause un error. ¡Y una buena razón para preferir 'x = 0' como asignación sobre' x <-0'! –

23

x = y = 5 es equivalente a x = (y = 5), debido a que la operadores de asignación "grupo" de derecha a izquierda, la cual trabaja. Significado: asignar 5 a y, dejando el número 5; y luego asigne ese 5 a x.

Esto no es lo mismo que (x = y) = 5, que no funciona. Significado: asigne el valor de y a x, dejando el valor de y; y luego asignar 5 a, umm, ¿qué exactamente?

Al mezclar los diferentes tipos de operadores de asignación, <- se ajusta más estrictamente que =. Por lo tanto, x = y <- 5 se interpreta como x = (y <- 5), que es el caso que tiene sentido.

Desafortunadamente, x <- y = 5 se interpreta como (x <- y) = 5, que es el caso que no funciona!

Consulte ?Syntax y ?assignOps para conocer las reglas de precedencia (vinculación) y agrupación.

4

Esto también puede añadir a la comprensión de la diferencia entre esos dos operadores:

df <- data.frame(
     a = rnorm(10), 
     b <- rnorm(10) 
) 

Para el primer elemento R ha asignado valores y nombre propio, mientras que el nombre del segundo elemento parece un poco extraño.

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 versión 3.3.2 (2016-10-31); macOS Sierra 10.12.1

+4

¿Puedes dar una explicación más detallada de por qué sucede esto/qué está pasando aquí? (sugerencia: 'data.frame' intenta usar el nombre de la variable proporcionada como el nombre del elemento en el marco de datos) –

+0

Solo pensé, ¿podría ser esto un error? Y si es así, ¿cómo y dónde lo informo? –

+1

no es un error. Traté de insinuar la respuesta en mi comentario anterior. Al establecer el nombre del elemento, R usará el equivalente de 'make.names (" b <- rnorm (10) ")'. –

Cuestiones relacionadas