为了账号安全,请及时绑定邮箱和手机立即绑定

RStudio和R中的运算符“ [<-”

RStudio和R中的运算符“ [<-”

心有法竹 2019-11-03 14:04:02
偶然地,我遇到了"[<-"操作员的奇怪行为。根据调用顺序以及我使用的是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:10x[5] <- 123"[<-"(x, 1, 111)x[1] 111   2   3   4   123   6   7   8   9  10但这只会在我使用普通R时发生!在RStudio中,两个选项的行为相同。我已经在两台机器上进行了检查(一台装有Fedora,一台装有Win7),情况看起来完全一样。我知道“功能性”版本("[<-"(x..))可能从未使用过,但我很好奇为什么会这样。谁能解释一下?=========================编辑:好的,所以从评论中我得到的原因是x <- 1:10类型为'integer'并在替换后x[5] <- 123为'double'。但是仍然有一个疑问,为什么RStudio中的行为会有所不同?我重新启动R会话,它没有任何改变。
查看完整描述

1 回答

?
30秒到达战场

TA贡献1828条经验 获得超6个赞

Rstudio的行为

Rstudio的对象浏览器以一种强制修改后复制的方式修改它检查的对象。具体来说,对象浏览器使用至少一个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中[<-的可变行为

[<-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"

# [1]   1   2


## Appending to X

"[<-"(X, 3, 100L)

X

# [1]   1   2

但是,只要有可能,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



查看完整回答
反对 回复 2019-11-04
  • 1 回答
  • 0 关注
  • 811 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信