Ric*_*rta 8 r variable-assignment
使用时注意到以下内容'[<-'.我成功地替换了元素,但没有在向量中添加元素.
例:
VarX <- integer()
VarX[1] <- 11
`[<-`(VarX, 2, 22)
VarX
# [1] 11
# Expected the value of VarX to be:
# [1] 11 22
# Also tried:
`[<-`(VarX, i=2, value=22)
VarX
# [1] 11
Run Code Online (Sandbox Code Playgroud)
但是,如果索引中已存在值,则会替换该值.
VarX <- integer()
VarX[1] <- 11
VarX[2] <- 99
VarX
# [1] 11 99
`[<-`(VarX, 2, 22)
VarX
# [1] 11 22
Run Code Online (Sandbox Code Playgroud)
我只是简单地使用了语法错误,或者这是否符合预期?任何进一步了解这里发生的事情将不胜感激.
请注意,除了更好地理解语言之外,这里没有具体的目标.
似乎行为与最初分配对象的值有关.例如,当分配给所述值VarX是1:2相对于c(1, 2)的行为[<-(VarX, 2, 22)给出不同的结果,如下所示:
###更改未保存到VarX
rm(VarX) # actually ran: rm(list=ls(all=TRUE))
VarX <- 1:2
VarX
# [1] 1 2
`[<-`(VarX, 2, 22)
# [1] 1 22
VarX
# [1] 1 2
Run Code Online (Sandbox Code Playgroud)
###更改保存到VarX
rm(VarX) # actually ran: rm(list=ls(all=TRUE))
VarX <- c(1, 2)
VarX[2] <- 2
VarX
# [1] 1 2
`[<-`(VarX, 2, 22)
# [1] 1 22
VarX
# [1] 1 22
Run Code Online (Sandbox Code Playgroud)
> sessionInfo()
R version 2.15.1 (2012-06-22)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
Run Code Online (Sandbox Code Playgroud)
Mat*_*erg 11
该函数'[<-'可能不会替换其第一个参数中的任何内容.在某些情况下,它会复制对象并对其进行修改.
请参阅语言定义的第3.4.4节:
x[3:5] <- 13:15
The result of this commands is as if the following had been executed
‘*tmp*‘ <- x
x <- "[<-"(‘*tmp*‘, 3:5, value=13:15)
rm(‘*tmp*‘)
Run Code Online (Sandbox Code Playgroud)
如果x必须修改结构,这基本上就是运行的.然而,很明显,基于OP(以及其他人,包括我自己)的实验,该"[<-"功能可以就地修改元素.显然,如果要替换整个对象,就不能就地进行任何操作.
就地替代:
> x <- 1:2
> class(x)
[1] "integer"
> `[<-`(x, 2, 99L)
[1] 1 99
> x
[1] 1 99
Run Code Online (Sandbox Code Playgroud)
替换整个对象,因为类型已更改(在C函数中SubAssignTypeFix):
> x <- 1:2
> class(x)
[1] "integer"
> x[2] <- 99
> class(x)
[1] "numeric"
Run Code Online (Sandbox Code Playgroud)
替换对象的另一种情况是,对要修改的对象有多个引用时:
x <- 1:2
y <- x
`[<-`(x, 2, 99L)
## [1] 1 99
x
## [1] 1 2
Run Code Online (Sandbox Code Playgroud)
运行调试器下R表示关于间接经由被称为分配函数x[2] <- 99调用C功能do_set,而当分配功能是由名字叫做直接不调用此函数.
do_set调用defineVar修改适当环境的函数.在就地替换的情况下,对象在环境中替换自身,这是通过名称调用赋值函数导致对象被修改(未采集副本)的确切情况.
有趣的花絮(见这里:R对象身份)
#### R console:
x <- 1:2
.Internal(inspect(x))
## @26b27a8 13 INTSXP g0c1 [NAM(1)] (len=2, tl=0) 1,2
x[2] <- 99
#### gdb:
Breakpoint 7, do_set (call=0x2773640, op=0x169e668, args=0x2773870, rho=0x16c6b68) at eval.c:1732
(gdb) p s
## $135 = (SEXP) 0x192bee0
c
#### R console:
.Internal(inspect(x))
## @192bee0 14 REALSXP g0c2 [NAM(1)] (len=2, tl=0) 1,99
Run Code Online (Sandbox Code Playgroud)
要直接回答原始问题,在[<-放大矢量时,会复制一份.从功能EnlargeVector在subassign.c:113:
PROTECT(newx = allocVector(TYPEOF(x), newlen));
/* Copy the elements into place. */
...
Run Code Online (Sandbox Code Playgroud)
这是R 2.15.2,我是从源代码构建的,没有优化和调试信息.没有优化就很慢.