2016-06-24 12 views
-1

リストを初期化する最もメモリ効率の良い方法は、そのリストをループ内で使用して結果を格納する場合にどのようなものがRにあるのだろうかと思います。私は、ループ内でオブジェクトを成長させることは、計算効率に重大な打撃を与える可能性があるので、できるだけ避けようとしています。Rのループの前にリストを初期化する最もメモリ効率の良い方法は何ですか?

私の問題は次のとおりです。私は個別に処理したいいくつかのデータグループを持っています。私のコードの要点は、各グループを一度に1つずつ実行し、いくつかのt検定を行い、統計的に有意な結果(したがって、各グループの可変長結果)のみを返すループがあることです。これまでは、各反復の結果を格納するためにlength(groups)のリストを初期化しています。

私の主な質問は、オブジェクトがループ内で成長しないようにリストを初期化する方法です。

  • 初期設定にはlist = vector(mode = "list", length=length(groups))を実行するだけで十分ですか?
    • length(groups)のリストを作成するだけなので、私は懐疑的ですが、各エントリはNULLに等しくなります。私の懸案事項は、リストにデータを格納するためにループを繰り返すたびに、エントリがNULLから結果ベクトルになるたびにオブジェクトを再コピーするということです。その場合、リストを初期化するのは実際にはありません非常に良い行います。しかし、listの内部構造がどのように機能するのかわかりませんので、リストに格納されているベクトルへの参照を格納するだけで、再コピーは不要です。
  • 他のオプションは、リストの各要素を、結果が持つ可能性のある最大長のベクトルに初期化することです。
    • 有効な有効な結果の最大数がわかっているため、これは大きな問題ではありません。私がこのアプローチを取った場合、ループ内の結果ベクトルで各ベクトルを上書きします。メモリの最大量はすでに予約されているので、再コピー/拡張は発生しないことを願っています。しかし、私がこのアプローチを取ることは望ましくありません。もし、それが必要ではなく、上記の最初のオプションが十分なものであれば。以下は

私の問題

#initialize variables 
results = vector(mode="list", length=length(groups)) #the line of code in question 
y=1 
tTests = vector(length = length(singleGroup))  

#perform analysis on each group in groups 
for(group in groups) 
{ 
    #returns a vector of p values with one entry per element in group 
    tTests = tTestFunction(group) 
    results[[y]] = tTests<=0.05 
    y=y+1 
} 
+2

私は圧倒的多数がそうだと思います。「vector( "list"、length(groups))は、結果リストを初期化する方法です。質問は少し広いです。 –

+0

おもちゃの例で両方のアイデアをテストするのは簡単です。 – joran

答えて

1

あなたのコードを記述したいくつかの擬似コードは動作しませんので、それは悪い例です。これを考慮してください:

x <- vector("list", length = 4) 
tracemem(x) ## trace memory copies of "x" 
for (i in 1:4) x[[i]] <- rnorm(4) 

アップデート中には、xの余分なコピーはありません。だから心配することはありません。

@lmoの提案によれば、x <- list()を使用してこのリストを初期化しても、メモリコピーは発生しません。


コメント

私の答えの目的、あなたはコード実行中に行われた(可能な)メモリコピーをトレースするときに、tracememの使用を参照することです。あなたがこの機能を知っていれば、ここで私たちに聞いてはいけません。

Hereは、tracememと関連して作成された私の他の回答です。しかし、それは別の文脈にある。そこで、メモリコピーが行われたときに返すものはtracememです。

+0

私の質問に記載されているように擬似コードであるため、コードが機能しません。私は、これを実践的な例を与えるのではなく、私が達成しようとしている論理的な枠組みを示すために含めました(これは複雑なコードチャンクのほんの一部です)。答えに感謝します。「トレーススメム」はかなり便利です。 – Cole

+1

'tracemem()'はメモリの再割り当てを報告していません。理由はわかりません。外側のベクトルが各代入で再割り当てされるのを見るには '.Internal(inspect(x))'を使います(出力の最初の行の '@ ...'はリストのメモリアドレスです;当初の配分が十分ではなかったために「あるべきである」)。個々の要素は複製されませんが、i = 2の場合は1つのコピー、i = 3の場合は2つのコピー、n(n-1)/約2つのコピー(2次スケーリング)の場合はリストにコピーされます。 。 –

+1

'inspect()'は、各シンボルに関する情報を要約するCレベルの関数です。 http://stackoverflow.com/questions/18359940/r-programming-vector-a1-2-avoid-copying-the-whole-vector/18361181#18361181とStackOverflowの他の場所に詳細があります。 –

関連する問題