函数`[< -`将_replace_一个元素,但不追加_element_

时间:2013-03-02 19:32:40

标签: 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

但是,如果索引处已存在值,则会替换该值。

VarX <- integer()
VarX[1] <- 11
VarX[2] <- 99
VarX
# [1] 11 99
`[<-`(VarX, 2, 22)
VarX
# [1] 11 22

我是否只是语法错误,或者这是否符合预期?任何进一步的洞察力 这里发生的事情将不胜感激。

请注意,除了更好地理解语言之外,这里没有具体的目标。

关于@Roland和@Dason的评论的更新。

似乎行为与最初分配对象值的方式有关。例如,当分配给VarX的值为1:2而非c(1, 2)时, [&lt; - (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

###更改保存到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

<小时/>

> 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  

1 个答案:

答案 0 :(得分: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*‘)

如果必须修改x的结构,这基本上就会运行。但是,很明显,基于OP(以及其他人,包括我自己)的实验,"[<-"函数可以就地修改元素。显然,如果要替换整个物体,就不能就地进行任何操作。

就地替代:

> x <- 1:2
> class(x)
[1] "integer"
> `[<-`(x, 2, 99L)
[1]  1 99
> x
[1]  1 99

替换整个对象,因为类型已更改(在C函数SubAssignTypeFix中):

> x <- 1:2
> class(x)
[1] "integer"
> x[2] <- 99
> class(x)
[1] "numeric"

替换对象的另一种情况是,对要修改的对象有多个引用时:

x <- 1:2
y <- x
`[<-`(x, 2, 99L)
## [1]  1 99
x
## [1] 1 2

在调试器下运行R表明通过x[2] <- 99间接调用的赋值函数调用C函数do_set,而直接按名称调用赋值函数时不调用此函数

do_set调用函数defineVar来修改适当的环境。在就地替换的情况下,对象在环境中替换它自己,这是通过名称调用赋值函数导致对象被修改(没有复制)的确切情况。

有趣的花絮(见这里:R object identity

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

要直接回答原始问题,当[<-放大矢量时,会复制一份副本。来自EnlargeVector的函数subassign.c:113

PROTECT(newx = allocVector(TYPEOF(x), newlen));

/* Copy the elements into place. */
...

这是R 2.15.2,我是从源代码构建的,没有优化和调试信息。没有优化就很慢。