24

R でリストを作成し、次のように追加するとします。

x = list(10)
x[[2]] = 20

これは同等ですか

x = list(10)
x = list(10, 20)

? 私は、R がメモリ内のリストをどのように処理するかについての特定の詳細についてはあまり経験していませんが、R はコピー ハッピーになる傾向があるということを限定的に理解しています。私にとって理想的なのは、最初のオプションが本質的にメモリ内に別のリストを作成することを伴わず、追加された値のためにメモリ内に新しい場所を確保することになるということです。基本的に、大きなリストがある場合、それに何かを追加したいだけなら、R に別のコピーを作成させたくありません。

私が望む動作がここで与えられたものではない場合、望ましい効果を得ることができる他の方法はありますか?

4

4 に答える 4

17

答えは「いいえ」であると確信しています。次のコードを使用して再確認しました。

Rprof(tmp <- tempfile(), memory.profiling = TRUE)

x <- list()
for (i in 1:100) x[[i]] <- runif(10000)

Rprof()
summaryRprof(tmp, memory = "stats")
unlink(tmp)

出力:

# index: runif
#      vsize.small  max.vsize.small      vsize.large  max.vsize.large 
#            76411           381781           424523          1504387 
#            nodes        max.nodes     duplications tot.duplications 
#          2725878         13583136                0                0 
#          samples 
#                5 

関連する部分はduplications = 0.

于 2012-10-07T20:35:12.937 に答える
12

ここでの Matthew Dowle の回答と、多くのメモリ効率の背後にある理論的根拠は<-、 、[<-[[<-およびその他の基本R操作 (namesなど)による多数の舞台裏のコピーを停止することです。

[[<-の全体をコピーしますx。以下の例を参照してください

x <- list(20)
 tracemem(x)
#[1] "<0x2b0e2790>"
 x[[2]] <- 20
# tracemem[0x2b0e2790 -> 0x2adb7798]: 

あなたの2番目のケース

x <- list(10,20)

実際にはオリジナルを追加するのではなく、追加された値を持つオリジナルであるオブジェクトにx置き換えます。xx

于 2012-10-07T22:25:10.653 に答える
9

リストを変更することでディープコピーが作成されるのか、シャローコピーが作成されるのかを判断するために、小さな実験を設定しました。リストを変更するとディープコピーが作成される場合、小さなオブジェクトを含むリストと比較して、大きなオブジェクトを含むリストを変更する場合は遅くなります。

z1 <- list(runif(1e7))
z2 <- list(1:10)

system.time({
  for(i in 1:1e4) z1[1 + i] <- 1L
})
#  user  system elapsed
# 0.283   0.034   0.317
system.time({
  for(i in 1:1e4) z2[1 + i] <- 1L
})
#  user  system elapsed
# 0.284   0.034   0.319

私のコンピューターのタイミングは基本的に同じで、リストをコピーすると浅いコピーが作成され、既存のデータ構造へのポインターがコピーされることを示唆しています。

于 2012-10-08T14:35:18.180 に答える
5

flodel の回答を受け入れましたが、Chase のヒントは良かったので、使用するという彼の提案を使用して、望ましい動作をしていることを確認しましたtracemem()。リストに追加するだけの最初の例を次に示します。

x = list(10)
tracemem(x[[1]])
# [1] "<0x2d03fa8>" #(likely different on each machine)
x[[2]] = 20
tracemem(x[[1]])
# [1] "<0x2d03fa8>"

そして、これが 2 番目の例の結果です。ここでは、2 つのリストを作成します。

x = list(10)
tracemem(x[[1]])
# [1] "<0x2d03c78>"
x = list(10, 20)
tracemem(x[[1]])
# [1] "<0x2d07ff8>"

したがって、最初の方法は、望ましい動作を与えるように見えます。

于 2012-10-07T20:51:14.230 に答える