函数 `[<-` 将 _replace_ 一个元素,但不附加一个 _element_ [英] Function `[<-` will _replace_ an element, but not append an _element_

查看:20
本文介绍了函数 `[<-` 将 _replace_ 一个元素,但不附加一个 _element_的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 '[<-' 时注意到以下内容.我成功地替换元素,但不能追加一个元素到向量.

I noticed the following when using '[<-'. I am successful at replacing elements but not at appending an element to the vector.

示例:

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

但是,如果索引处已经有一个值,则该值会被替换.

However, if there is already a value at the index, the value does get replaced.

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

我只是语法错误,还是按预期进行?任何进一步的了解这里发生的事情将不胜感激.

Do I simply have the syntax wrong, or is this as intended? Any further insight into what is going on here would be appreciated.

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

该行为似乎与最初分配对象值的方式有关.例如,当分配给 VarX 的值是 1:2c(1, 2) 的行为>[<-(VarX, 2, 22) 给出不同的结果,如下图:

It appears that the behavior is tied to how the values of the object are initially assigned. For example, when the value assigned to VarX is 1:2 versus c(1, 2) the behavior of [<-(VarX, 2, 22) gives different results, as shown below:

### 更改未保存到 VarX

### changes not saved to 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

### changes ARE saved to 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  

推荐答案

函数 '[<-' 可能不会替换其第一个参数中的任何内容.在某些情况下,它会复制对象并对其进行修改.

The function '[<-' might not replace anything in its first argument. In certain circumstances, it makes a copy of the object and modifies that.

参见语言定义的第 3.4.4 节:

See section 3.4.4 of the language definition:

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(以及其他人,包括我自己)的实验,很明显 "[<-" 函数可以就地修改元素.显然,如果要替换整个对象,则无法就地完成任何操作.

This is essentially what will be run if the structure of x must be modified. However, it is clear based on experiments of the OP (and others, including myself) that the "[<-" function can modify elements in-place. Clearly nothing can be done in-place if the entire object is going to be replaced.

就地替换:

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

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

Replacement of the entire object because the type has been changed (in the C function SubAssignTypeFix):

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

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

Another situation where the object is replaced, is when there is more than one reference to the object being modified:

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

在调试器下运行R显示,通过x[2] <- 99间接调用的赋值函数调用了C函数do_set,而直接按名称调用赋值函数时,不会调用该函数.

Running R under the debugger shows that the assignment function called indirectly via x[2] <- 99 invokes the C function do_set, whereas this function is not called when the assignment function is called directly by name.

do_set 调用一个函数 defineVar 来修改适当的环境.在就地替换的情况下,对象在环境中替换自身,这正是按名称调用赋值函数导致对象被修改(未获取副本)的确切情况.

do_set calls a function defineVar which modifies the appropriate environment. In the case of an in-place replacement, the object replaces itself in the environment, which are the exact cases where calling the assignment function by name results in the object being modified (a copy was not taken).

有趣的花絮(参见此处:R 对象标识)

Interesting tidbit (and see here: 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

直接回答原问题,当[<-放大向量时,复制一份.来自 subassign.c:113 处的 EnlargeVector 函数:

To directly answer the original question, when [<- enlarges the vector, a copy is made. From the function EnlargeVector at subassign.c:113:

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

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

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

This is R 2.15.2, which I built from source without optimization and with debugging info. It is very slow without optimization.

这篇关于函数 `[&lt;-` 将 _replace_ 一个元素,但不附加一个 _element_的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆