运算符“[< – ”在RStudio和R中

偶然我遇到了"[<-"运算符的奇怪行为。 它的行为有所不同,具体取决于调用的顺序,以及我是使用RStudio还是普通的RGui。 我会用一个例子来说明一下。

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

据我所知,第一个分配不应该改变x (或者也许我错了?),而第二个应该做的。 而实际上上述操作的结果是

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

但是,当我们以不同的顺序执行这些操作时,结果是不同的, x已经改变了! 意味深长:

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

但只有当我使用普通的R才会发生! 在RStudio中,这两个选项的行为是相同的。 我已经检查了两台机器(一个与Fedora的一个与Win7),情况看起来完全一样。 我知道'function'版本( "[<-"(x..) )可能从来没有使用过,但我很好奇它为什么发生。 谁能解释一下吗?

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

编辑:好的,所以从评论我得到的原因是, x <- 1:10有types'整数'和取代x[5] <- 123它是'双'。 但是仍然有问题,为什么RStudio中的行为不同? 我重新启动R会话,它不会改变任何东西。

Rstudio的行为

Rstudio的对象浏览器以修改后强制复制的方式修改它检查的对象。 具体来说,对象浏览器使用至less一个R函数,其内部调用对对象进行强制评估,在过程中将对象的已命名字段的值从1重置为2.从R-Internals手册 :

当一个对象即将被改变时,被指定的字段被查询。 值为2意味着对象必须在被更改之前被复制。 […]值为1的情况下,原则上两个a的副本在计算期间存在,但不再是,因此可以优化一些原始函数在这种情况下避免副本。

要查看对象浏览器修改下一个代码块中的命名字段( [NAM()] ),请比较运行以下行的结果。 首先,这两个“行”是一起运行的,所以Rstudio在查询结构之前没有时间“碰” X 在第二行中,每一行都被分开粘贴,所以X在被检查之前被修改。

 ## 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,... 

一旦命名的字段设置为2, [<-(X, ...)将不会修改原始对象。 将以下内容粘贴到Rstudio中,一次修改X ,而不是逐行粘贴:

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

所有这一切的另一个结果是,Rstudio的对象浏览器实际上使一些操作比其他方式慢。 再次比较一下先粘贴在一起的两个命令,然后再一次一个:

 ## 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 

[< – 在R中的variables行为

[<- wrt修改向量X的行为取决于X的存储types和被分配给它的元素的存储types。 这解释了R的行为,但不是Rstudio的行为。

在R中,当[<-要么附加到向量X ,要么执行要求修改X的types的子分配时,复制X ,并且返回的值不会覆盖预先存在的variablesX (要做到这一点,你需要做一些像X <- "[<-(X, 2, 100)

所以,以下都不要修改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 

尽pipe如此,R确实允许[<-函数直接通过引用修改X (即不进行复制)。 这里的“可能”包括子分配不需要修改X的types的情况。

所以下面的所有修改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