[解決済み】data.tableが他のdata.tableの参照である場合(コピーである場合)を正確に理解する。
質問
の参照渡しのプロパティを理解するのに少し苦労しています。
data.table
. いくつかの操作は参照を「壊す」ようで、何が起こっているのか正確に理解したいと思います。
を作成する際に
data.table
から別の
data.table
(経由
<-
で新しいテーブルを更新し、さらに
:=
の場合、元のテーブルも変更されます。これは、予想通りです。
?data.table::copy
そして
stackoverflow: データテーブルパッケージの参照渡しの演算子
以下はその例です。
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
が変更されなくなりました。
DT = data.table(a=c(1,2), b=c(11,12))
newDT <- DT
newDT$b[2] <- 200 # new operation
newDT[1, a := 100]
print(DT)
# a b
# [1,] 1 11
# [2,] 2 12
ということで、どうやら
newDT$b[2] <- 200
の行は、何らかの形で参照を「破壊」しています。これは何らかの形でコピーを呼び出しているのだと思いますが、自分のコードに潜在的なバグを持ち込まないようにするために、Rがこれらの操作をどのように扱っているかを完全に理解したいと思います。
どなたか解説していただけると大変ありがたいです。
どのように解決するのですか?
そうです、Rのサブアサインメントです。
<-
(または
=
または
->
のコピーを作成する)。
全体
オブジェクトを作成します。それをトレースするには
tracemem(DT)
と
.Internal(inspect(DT))
は、以下のとおりです。また
data.table
特徴
:=
と
set()
は、渡されたオブジェクトへの参照で代入します。したがって、もしそのオブジェクトが以前に(サブアサインされた
<-
または明示的な
copy(DT)
) の場合、参照によって変更されるのはコピーです。
DT <- data.table(a = c(1, 2), b = c(11, 12))
newDT <- DT
.Internal(inspect(DT))
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,12
# ATTRIB: # ..snip..
.Internal(inspect(newDT)) # precisely the same object at this point
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,12
# ATTRIB: # ..snip..
tracemem(newDT)
# [1] "<0x0000000003b7e2a0"
newDT$b[2] <- 200
# tracemem[0000000003B7E2A0 -> 00000000040ED948]:
# tracemem[00000000040ED948 -> 00000000040ED830]: .Call copy $<-.data.table $<-
.Internal(inspect(DT))
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),TR,ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,12
# ATTRIB: # ..snip..
.Internal(inspect(newDT))
# @0000000003D97A58 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040ED7F8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040ED8D8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,200
# ATTRIB: # ..snip..
にも注目してください。
a
ベクターがコピーされました(異なる16進数の値はベクターの新しいコピーを示します)。
a
は変更されていない。の全体も変更されていません。
b
がコピーされ、変更する必要のある要素だけが変更されたのではありません。これは大きなデータでは避けるべき重要なことで、なぜ
:=
と
set()
に導入されました。
data.table
.
さて、コピーした
newDT
を参照することで、それを変更することができます。
newDT
# a b
# [1,] 1 11
# [2,] 2 200
newDT[2, b := 400]
# a b # See FAQ 2.21 for why this prints newDT
# [1,] 1 11
# [2,] 2 400
.Internal(inspect(newDT))
# @0000000003D97A58 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040ED7F8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040ED8D8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,400
# ATTRIB: # ..snip ..
3つの16進数値(列点のベクトル、2列の各列)はすべて変更されていないことに注意してください。つまり、全くコピーをせずに、本当に参照によって変更されたのです。
あるいは、元の
DT
を参照してください。
DT[2, b := 600]
# a b
# [1,] 1 11
# [2,] 2 600
.Internal(inspect(DT))
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,600
# ATTRIB: # ..snip..
これらの16進数の値は、私たちが最初に見た
DT
上記の タイプ
example(copy)
を使用する他の例については
tracemem
との比較
data.frame
.
もし、あなたが
tracemem(DT)
では
DT[2,b:=600]
をクリックすると、1つのコピーが報告されます。このコピーは
print
メソッドが行います。でラップした場合
invisible()
または関数やスクリプトの中で呼び出された場合は
print
メソッドは呼び出されません。
これはすべて、関数の内部にも当てはまります。
:=
と
set()
は、たとえ関数内であっても、書き込み時にコピーされません。ローカルなコピーを変更する必要がある場合は
x=copy(x)
を関数の先頭で実行します。ただし
data.table
は大きなデータのためのものです(小さなデータのためのプログラミングの高速化という利点もあります)。我々は意図的に大きなオブジェクトをコピーしたくないのです(絶対に)。その結果、通常のワーキングメモリー倍率3倍を許容する必要はありません。私たちは、1列分のワーキングメモリしか必要としないようにしています(つまり、ワーキングメモリの係数は3ではなく1/ncolです)。
関連
-
[解決済み】Rで「パッケージ'FILE_PATH'のインストールで終了ステータスが0でなかった」。
-
[解決済み] テスト
-
[解決済み】rbind エラー。"名前が以前の名前と一致しない"
-
[解決済み】apply()とadply()の出力が異なる件)
-
[解決済み】 boxplotに色を追加する - "離散的なスケールに連続的な値が供給される "エラー
-
[解決済み】長いオブジェクトの長さは、短いオブジェクトの長さの倍数ではない?[重複]。
-
[解決済み】r Error dim(X) must have a positive length?
-
[解決済み] 因子を日付形式に変換するにはどうすればいいですか?
-
[解決済み】Rでデータフレームのサブセットをプロットする方法は?
-
[解決済み] PHPの配列を別の配列にコピーする関数はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Stataバージョン5-12の.dtaファイルではない
-
[解決済み】Rで「パッケージ'FILE_PATH'のインストールで終了ステータスが0でなかった」。
-
[解決済み】ベースグラフィックスでプロットエリアの外側に凡例をプロットする?
-
[解決済み】Rのメモリ管理/サイズn Mbのベクトルを割り当てられない
-
[解決済み】match.fun(FUN)でのエラーについて)
-
[解決済み】rbind(deparse.level, ...)でエラー:引数の列の数がRにマッチしていない
-
[解決済み] 因子を日付形式に変換するにはどうすればいいですか?
-
[解決済み】各グループの上位3要素を計算する際に「数値型、論理型、複合型でのみ可能な演算」を回避する方法
-
[解決済み】R4DSのエラー比較(1)は、アトミック型とリスト型でのみ可能です
-
[解決済み】dplyr: "Error in n(): 関数は直接呼ばれるべきではありません"