R:メモリを使い果たすことなく2つの巨大なデータフレームをバインドする方法
-
16-10-2019 - |
質問
2つのデータフレームがあります df1
と df2
それぞれに約1,000万列と4列があります。私はそれらをRODBC/SQLQUERYを使用して問題なく読みますが、私がしようとするとき rbind
彼ら、私はRエラーメッセージの最も恐ろしいものを手に入れます: cannot allocate memory
. 。より効率的な方法が必要です rbind
より効率的に - 誰もが共有したいこれについてお気に入りのトリックを持っていますか?たとえば、私はこの例をドキュメントで見つけました sqldf
:
# rbind
a7r <- rbind(a5r, a6r)
a7s <- sqldf("select * from a5s union all select * from a6s")
それはそれを行うための最良/推奨方法ですか?
アップデート重要なものを使用して動作するようになりました dbname = tempfile()
の議論 sqldf
JD Longが彼の答えで示唆しているように、上記で電話してください この質問
解決
最初にRに読み取り、それらを組み合わせるのではなく、SQLiteにそれらを読み取り、それらを組み合わせてからRに送信することができます。
# create two sample files
DF1 <- data.frame(A = 1:2, B = 2:3)
write.table(DF1, "data1.dat", sep = ",", quote = FALSE)
rm(DF1)
DF2 <- data.frame(A = 10:11, B = 12:13)
write.table(DF2, "data2.dat", sep = ",", quote = FALSE)
rm(DF2)
# now we do the real work
library(sqldf)
data1 <- file("data1.dat")
data2 <- file("data2.dat")
sqldf(c("select * from data1",
"insert into data1 select * from data2",
"select * from data1"),
dbname = tempfile())
これは与える:
> sqldf(c("select * from data1", "insert into data1 select * from data2", "select * from data1"), dbname = tempfile())
A B
1 1 2
2 2 3
3 10 12
4 11 13
この短いバージョンは、Row Orderが重要でない場合にも機能します。
sqldf("select * from data1 union select * from data2", dbname = tempfile())
SQLDFホームページを参照してください http://sqldf.googlecode.com と ?sqldf
詳細については。それらは近いが同一ではないので、ファイル形式の引数に特に注意を払ってください read.table
. 。ここでは、デフォルトを使用したので、問題はあまりありませんでした。
他のヒント
data.table
数百万を超えるレコードを持つオブジェクトの効率的な操作用のRパッケージ。
そのパッケージのバージョン1.8.2が提供しています rbindlist
あなたが望むものを非常に効率的に達成できる機能。したがって、の代わりに rbind(a5r, a6r)
あなたはできる:
library(data.table)
rbindlist(list(a5r, a6r))
aを作成してみてください data.frame
目的のサイズのため、添え字を使用してデータをインポートします。
dtf <- as.data.frame(matrix(NA, 10, 10))
dtf1 <- as.data.frame(matrix(1:50, 5, 10, byrow=TRUE))
dtf2 <- as.data.frame(matrix(51:100, 5, 10, byrow=TRUE))
dtf[1:5, ] <- dtf1
dtf[6:10, ] <- dtf2
私はそうだと思います rbind
その寸法を事前に割り当てることなくオブジェクトを成長させます...私は肯定的に確信していません、これは単なる推測です。今夜、「R Inferno」または「データ操作」を揺さぶる。多分 merge
トリックをします...
編集
そして、あなたのシステムおよび/またはRがそれほど大きなものに対処できないことを(おそらく)覚えておく必要があります。 Revolutionrを試してみてください。たぶん、時間/リソースを節約することができます。
ユニオンのトピックに関するこのスレッドの完全性については、大きなファイルを作成するには、ファイルにシェルコマンドを使用してそれらを結合してみてください。 Windowsでは、「/b」フラグを備えた「コピー」コマンドです。例:
system(command =
paste0(
c("cmd.exe /c COPY /Y"
, '"file_1.csv" /B'
, '+ "file_2.csv" /B'
, '"resulting_file.csv" /B'
), collapse = " "
)
)#system
ファイルにはヘッダーがなく、同じ区切り文字などが必要です。シェルコマンドの速度と汎用性は大きな利益であることがあるので、データフローをマッピングするときはcli-commandsを忘れないでください。