29

2つの大きなデータフレームを作成する必要があります。今使っています

df <- rbind(df, df.extension)

しかし、私は(ほとんど)即座にメモリを使い果たします。dfがメモリに2回保持されているからだと思います。将来的にはさらに大きなデータフレームが表示される可能性があるため、何らかのインプレースrbindが必要です。

だから私の質問は:rbindを使用するときにメモリ内のデータの重複を回避する方法はありますか?

SqlLiteを使用するこの質問を見つけましたが、ハードドライブをキャッシュとして使用することは避けたいと思います。

4

4 に答える 4

19

data.tableあなたの友だちです!

Cf http://www.mail-archive.com/r-help@r-project.org/msg175877.html


nikolaのコメントに続いて、ここに?rbindlistの説明があります(v1.8.2の新機能):

と同じdo.call("rbind",l)ですが、はるかに高速です。

于 2012-08-18T12:49:53.347 に答える
18

まず第一に:あなたが安全になりたいのであれば、あなたがリンクしている他の質問からの解決策を使用してください。Rは値による呼び出しであるため、メモリ内のデータフレームをコピーしない「インプレース」メソッドについては忘れてください。

かなりのメモリを節約するための推奨されない方法の1つは、データフレームがリストであると偽って、forループを使用してリストを強制し(適用すると地獄のようにメモリを消費します)、Rに実際にデータフレームであると信じ込ませることです。

もう一度警告します。これをより複雑なデータフレームで使用すると、問題が発生し、バグを見つけるのが困難になります。したがって、十分にテストするようにしてください。可能であれば、これはできるだけ避けてください。

次のアプローチを試すことができます:

n1 <- 1000000
n2 <- 1000000
ncols <- 20
dtf1 <- as.data.frame(matrix(sample(n1*ncols), n1, ncols))
dtf2 <- as.data.frame(matrix(sample(n2*ncols), n1, ncols))

dtf <- list()

for(i in names(dtf1)){
  dtf[[i]] <- c(dtf1[[i]],dtf2[[i]])
}

attr(dtf,"row.names") <- 1:(n1+n2)
attr(dtf,"class") <- "data.frame"

それはあなたが実際に持っていた行名を消去します(あなたはそれらを再構築することができますが、重複した行名をチェックしてください!)。また、rbindに含まれる他のすべてのテストを実行するわけではありません。

私のテストではメモリの約半分を節約できます。私のテストでは、dtfcombとdtfの両方が同じです。赤いボックスはrbindで、黄色のボックスは私のリストベースのアプローチです。

ここに画像の説明を入力してください

テストスクリプト:

n1 <- 3000000
n2 <- 3000000
ncols <- 20

dtf1 <- as.data.frame(matrix(sample(n1*ncols), n1, ncols))
dtf2 <- as.data.frame(matrix(sample(n2*ncols), n1, ncols))

gc()
Sys.sleep(10)
dtfcomb <- rbind(dtf1,dtf2)
Sys.sleep(10)
gc()
Sys.sleep(10)
rm(dtfcomb)
gc()
Sys.sleep(10)
dtf <- list()
for(i in names(dtf1)){
  dtf[[i]] <- c(dtf1[[i]],dtf2[[i]])
}
attr(dtf,"row.names") <- 1:(n1+n2)
attr(dtf,"class") <- "data.frame"
Sys.sleep(10)
gc()
Sys.sleep(10)
rm(dtf)
gc()
于 2011-08-17T14:34:09.833 に答える
11

今、私は次の解決策を考え出しました:

nextrow = nrow(df)+1
df[nextrow:(nextrow+nrow(df.extension)-1),] = df.extension
# we need to assure unique row names
row.names(df) = 1:nrow(df)

今、私はメモリを使い果たしません。保管しているからだと思います

object.size(df) + 2 * object.size(df.extension)

rbindを使用すると、Rが必要になります

object.size(rbind(df,df.extension)) + object.size(df) + object.size(df.extension). 

その後、私は使用します

rm(df.extension)
gc(reset=TRUE)

もう必要のないメモリを解放するために。

これで今のところ私の問題は解決しましたが、メモリ効率の高いrbindを実行するためのより高度な方法があると感じています。このソリューションについてのコメントに感謝します。

于 2011-08-18T08:43:36.667 に答える
5

これはの完璧な候補ですbigmemory。詳細については、サイトを参照してください。考慮すべき3つの使用法の側面は次のとおりです。

  1. HDを使用しても問題ありません。HDへのメモリマッピングは、他のどのアクセスよりもはるかに高速であるため、速度の低下は見られない場合があります。時々、私は1TBを超えるメモリマップドマトリックスに依存しますが、ほとんどは6〜50GBです。さらに、オブジェクトマトリックスであるため、オブジェクトを使用するためにコードを書き換えるという実際のオーバーヘッドは必要ありません。
  2. ファイルベースの行列を使用するかどうかに関係なく、を使用separated = TRUEして列を分離できます。私の3番目のヒントのため、私はこれほど多くは使用していません。
  3. HDスペースを過剰に割り当てて、潜在的なマトリックスサイズを大きくすることができますが、対象のサブマトリックスのみをロードします。このようにする必要はありませんrbind

注:元の質問ではデータフレームとbigmemoryがマトリックスに適していますが、本当に必要な場合は、さまざまなタイプのデータに対してさまざまなマトリックスを簡単に作成し、RAM内のオブジェクトを組み合わせてデータフレームを作成できます。

于 2011-08-17T14:57:32.257 に答える