运算符"[< - "在RStudio和R中

Bar*_*kCh 42 r rstudio

偶然我遇到了"[<-"操作员的奇怪行为.它的行为会有所不同,具体取决于调用的顺序以及我是使用RStudio还是普通的RGui.我将通过一个例子说清楚.

x <- 1:10
"[<-"(x, 1, 111)
x[5] <- 123
Run Code Online (Sandbox Code Playgroud)

据我所知,第一个分配不应该改变x(或者我可能是错的?),而第二个应该这样做.事实上,上述操作的结果是

x
[1]  1  2  3  4  123  6  7  8  9 10
Run Code Online (Sandbox Code Playgroud)

但是,当我们以不同的顺序执行这些操作时,结果会有所不同并且x已经发生变化!意味深长:

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

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

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

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

Jos*_*ien 36

Rstudio的行为

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

当一个对象即将被更改时,将查询指定的字段.值为2表示在更改之前必须复制对象.[...]值1用于情况,其中原则上在计算的持续时间内存在两个副本[...]但不再存在,因此可以优化一些原始函数在这种情况下避免复制.

要查看对象浏览器修改命名字段([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,... 
Run Code Online (Sandbox Code Playgroud)

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

x <- 1:10
"[<-"(x, 1, 111)
Run Code Online (Sandbox Code Playgroud)

所有这一切的另一个后果是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 
Run Code Online (Sandbox Code Playgroud)

[< - 在R中的变量行为

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

在R中,当[<-附加到向量X或执行需要X修改类型的子分配时,X将复制并返回的值不会覆盖预先存在的变量X.(要做到这一点,你需要做类似的事情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
Run Code Online (Sandbox Code Playgroud)

但是,只要有可能,R确实允许[<-函数X通过引用直接修改(即不进行复制).这里的"可能"包括子赋值不要求X修改类型的情况.

所以以下所有修改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
Run Code Online (Sandbox Code Playgroud)

  • 我在R-Devel上给出了一个稍微全面的答案,但你不需要知道C来获得`class()`和`typeof()`之间区别的要点 - 只需在R提示符下输入它们即可.注意打印内容的区别. (3认同)
  • 我已经复制了你的最后一个例子,结果是一样的,但是在更换`"[< - "(X,2,20L)之前``我运行命令`typeof(X)`,然后替换不起作用(在RGUI).奇怪. (2认同)