8

を使用していて気になったのは以下の点'[<-'です。要素を置き換えることはできますが、ベクターに要素を追加することはできません。

例:

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 のコメントに関する更新。

この動作は、オブジェクトの値が最初に割り当てられた方法に関連付けられているようです。たとえば、に割り当てられた値が[<-の動作に対してVarXisに割り当てられた場合、以下に示すように異なる結果が得られます。1:2c(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

### 変更は 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  
4

1 に答える 1

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_setdefineVar適切な環境を変更する関数を呼び出します。インプレース置換の場合、オブジェクトは環境内でそれ自体を置き換えます。これは、代入関数を名前で呼び出すとオブジェクトが変更される (コピーが取得されない) 正確なケースです。

興味深い情報 (ここを参照してください: 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 で、最適化せずにデバッグ情報を使用してソースからビルドしました。最適化しないと非常に遅くなります。

于 2013-03-02T20:24:41.503 に答える