トミーのが最良の答えです。これはコメントするには大きすぎたので、答えとして追加してください...
DF
これは、( joranがコメントしたように、の全体の)コピーを自分で見る方法です:
> DF = data.frame(a=1:3,b=4:6)
> tracemem(DF)
[1] "<0x0000000003104800"
> for (i in 1:3) {DF$b[i] <- i; .Internal(inspect(DF))}
tracemem[0000000003104800 -> 000000000396EAD8]:
tracemem[000000000396EAD8 -> 000000000396E4F0]: $<-.data.frame $<-
tracemem[000000000396E4F0 -> 000000000399CDC8]: $<-.data.frame $<-
@000000000399CDC8 19 VECSXP g0c2 [OBJ,NAM(2),TR,ATT] (len=2, tl=0)
@000000000399CD90 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,3
@000000000399CCE8 13 INTSXP g0c2 [] (len=3, tl=0) 1,5,6
ATTRIB: # .. snip ..
tracemem[000000000399CDC8 -> 000000000399CC40]:
tracemem[000000000399CC40 -> 000000000399CAB8]: $<-.data.frame $<-
tracemem[000000000399CAB8 -> 000000000399C9A0]: $<-.data.frame $<-
@000000000399C9A0 19 VECSXP g0c2 [OBJ,NAM(2),TR,ATT] (len=2, tl=0)
@000000000399C968 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,3
@000000000399C888 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,6
ATTRIB: # .. snip ..
tracemem[000000000399C9A0 -> 000000000399C7E0]:
tracemem[000000000399C7E0 -> 000000000399C700]: $<-.data.frame $<-
tracemem[000000000399C700 -> 00000000039C78D8]: $<-.data.frame $<-
@00000000039C78D8 19 VECSXP g0c2 [OBJ,NAM(2),TR,ATT] (len=2, tl=0)
@00000000039C78A0 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,3
@0000000003E07890 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,3
ATTRIB: # .. snip ..
> DF
a b
1 1 1
2 2 2
3 3 3
これらの各行はtracemem[]
、オブジェクト全体のコピーに対応しています。a
への割り当てによって変更されていないにもかかわらず、列ベクトルの 16 進アドレスも毎回変更されていることがわかりますb
。
私の知る限り、自分でCコードにドロップすることなく、Rで(現在)data.frame
メモリのコピーをまったく使用せずに a のアイテムを変更する唯一の方法は、両方のパッケージ内の:=
演算子と関数です。Stack Overflow で here を使用した参照による割り当てに関する17 の質問があります。set()
data.table
:=
しかし、この場合、ループをまったく必要としないので、Tommy のワンライナーが間違いなく最適です。