6

自分自身のためにいくつかの問題を解決するために、コピーがいつ作成され、いつコピーされないかをよりよく理解したいと思いdata.tableます。this question が指摘しているように、 data.table が別の data.table への参照である場合 (vs のコピー) を正確に理解する場合、単純に次を実行すると、元のものが変更されます。

library(data.table)

DT <- data.table(a=c(1,2), b=c(11,12))
print(DT)
#      a  b
# [1,] 1 11
# [2,] 2 12

newDT <- DT        # reference, not copy
newDT[1, a := 100] # modify new DT

print(DT)          # DT is modified too.
#        a  b
# [1,] 100 11
# [2,]   2 12

ただし、これを行うと (たとえば)、新しいバージョンを変更することになります。

DT = data.table(a=1:10)
DT
     a
 1:  1
 2:  2
 3:  3
 4:  4
 5:  5
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

newDT = DT[a<11]
newDT
     a
 1:  1
 2:  2
 3:  3
 4:  4
 5:  5
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

newDT[1:5,a:=0L]

newDT
     a
 1:  0
 2:  0
 3:  0
 4:  0
 5:  0
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

DT
     a
 1:  1
 2:  2
 3:  3
 4:  4
 5:  5
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

私が理解しているように、これが発生する理由は、iステートメントを実行するdata.tableと、古い の選択要素によって占有されているメモリへの参照ではなく、まったく新しいテーブルが返されるためdata.tableです。これは正しいですか?

編集:申し訳ありませんが、そうではiありませんでしたj(上記で変更)

4

1 に答える 1

8

newDT2 番目の例で作成すると、 i(ではなくj) 評価されます。引数:=内で参照によって割り当てます。自己参照オーバーは列を割り当てますが、行は割り当てないため、ステートメントにjは同等のものはありません。i

Adata.tableはリストです。長さ == 列数ですが、過剰に割り当てられているため、テーブル全体をコピーせずに列を追加できます (例: :=inを使用j) 。

data.table を調べると、truelength( tl = 100) が表示されます。これは、列ポインタ スロットの数です。

 .Internal(inspect(DT))
@1427d6c8 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=1, tl=100)
  @b249a30 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,...

data.table 内では、各要素の長さ10は 、およびtl=0です。truelength現在、参照によって余分な行を追加できるように列を増やす方法はありません。

から?truelength

現在、過剰に割り当てられているのは列ポインターのリスト ベクトル (つまり、truelength(DT)) であり、列ベクトル自体ではありません。これにより、将来的に高速な行挿入 () が可能になります。

を評価するとidata.table元の行と同じ順序ですべての行が返されたかどうかをチェックせず (その場合はコピーのみをコピーしない)、単にコピーを返します。

于 2013-04-08T22:56:13.093 に答える