Operador “[<-" en RStudio y R

Por accidente, he encontrado un comportamiento extraño del operador "[<-" . Se comporta de manera diferente dependiendo del orden de las llamadas y si estoy usando RStudio o simplemente RGui ordinario. Me voy a aclarar con un ejemplo.

 x <- 1:10 "[<-"(x, 1, 111) x[5] <- 123 

Por lo que yo sé, la primera asignación no debería cambiar x (¿o quizás estoy equivocado?), Mientras que el segundo debería hacerlo. Y, de hecho, el resultado de las operaciones anteriores es

 x [1] 1 2 3 4 123 6 7 8 9 10 

Sin embargo, cuando realizamos estas operaciones en diferente orden, los resultados son diferentes y x ha cambiado. Con air significativo:

 x <- 1:10 x[5] <- 123 "[<-"(x, 1, 111) x [1] 111 2 3 4 123 6 7 8 9 10 

¡Pero solo sucede cuando estoy usando R simple! En RStudio, el comportamiento es el mismo en ambas opciones. Lo he comprobado en dos máquinas (una con Fedora uno con Win7) y la situación se ve exactamente igual. Sé que la versión ‘funcional’ ( "[<-"(x..) ) probablemente nunca se use, pero tengo mucha curiosidad de por qué está sucediendo. ¿Alguien podría explicar eso?

=======================

EDITAR: Ok, de los comentarios me sale que la razón fue que x <- 1:10 tiene tipo ‘entero’ y después de reemplazar x[5] <- 123 es ‘doble’. Pero todavía queda la pregunta de por qué el comportamiento es diferente en RStudio? Reinicio la sesión R y no cambia nada.

El comportamiento de Rstudio

El navegador de objetos de Rstudio modifica los objetos que examina de una manera que fuerza la copia al modificarlos. Específicamente, el buscador de objetos emplea al menos una función R cuya llamada fuerza internamente la evaluación del objeto, en el proceso restablece el valor del campo con nombre del objeto de 1 a 2. Del manual R-Internals :

Cuando un objeto está a punto de ser alterado, se consulta el campo nombrado. Un valor de 2 significa que el objeto debe duplicarse antes de cambiarse. […] Un valor de 1 se usa para situaciones […] en las que, en principio, existen dos copias de una durante la duración […] del cálculo pero no más, por lo que se pueden optimizar algunas funciones primitivas. para evitar una copia en este caso.

Para ver que el buscador de objetos modifica el campo nombrado ( [NAM()] en el siguiente bloque de código), compare los resultados de ejecutar las siguientes líneas. En el primero, ambas “líneas” se ejecutan juntas, de modo que Rstudio no tiene tiempo para “tocar” X antes de consultar su estructura. En el segundo, cada línea se pega por separado, por lo que X se modifica antes de examinarse.

 ## Pasted in together x <- 1:10; .Internal(inspect(x)) # @46b47b8 13 INTSXP g0c4 [NAM(1)] (len=10, tl=0) 1,2,3,4,5,... ## Pasted in with some delay between lines x <- 1:10 .Internal(inspect(x)) # @42111b8 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,... 

Una vez que el campo nombrado se establece en 2, [<-(X, ...) no modificará el objeto original. Pegar lo siguiente en Rstudio de una vez modifica X , mientras que pegarlo en línea por línea no:

 x <- 1:10 "[<-"(x, 1, 111) 

Una consecuencia más de todo esto es que el navegador de objetos de Rstudio en realidad hace que algunas operaciones sean más lentas de lo que serían de otra manera. Nuevamente, compare los mismos dos comandos primero pegados juntos, y luego uno a la vez:

 ## Pasted in together x <- 1:5e7 system.time(x[1] <- 9L) # user system elapsed # 0 0 0 ## Pasted in one at a time x <- 1:5e7 system.time(x[1] <- 9L) # user system elapsed # 0.11 0.04 0.16 

Comportamiento variable de [<- en R

El comportamiento de [<- wrt al modificar un vector X depende de los tipos de almacenamiento de X y del elemento que se le asigna. Esto explica el comportamiento de R pero no el de Rstudio.

En R, cuando [<- agrega a un vector X , o realiza una subasignación que requiere que se modifique el tipo de X , se copia X y el valor que se devuelve no sobrescribe la variable X existente. (Para hacer eso, necesitas hacer algo como X <- "[<-(X, 2, 100) .

Por lo tanto, ninguno de los siguientes modifica X

 X <- 1:2 ## Note: typeof(X) --> "integer" ## Subassignment that requires that X be coerced to "numeric" type "[<-"(X, 2, 100) ## Note: typeof(100) --> "numeric" X # [1] 1 2 ## Appending to X "[<-"(X, 3, 100L) X # [1] 1 2 

Sin embargo, siempre que sea posible, R permite que la función [<- modifique X directamente por referencia (es decir, sin hacer una copia). "Posible" aquí incluye casos en los que una asignación secundaria no requiere que se modifique el tipo de X

Entonces, todos los siguientes modifican X

 X <- c(0i, 0i, 0i, 0i) "[<-"(X, 1, TRUE) "[<-"(X, 2, 20L) "[<-"(X, 3, 3.14) "[<-"(X, 4, 5+5i) X # [1] 1.00+0i 20.00+0i 3.14+0i 5.00+5i