About connecting the dots.

data science related trivial things

Rで高速に大量データを読み込んでデータフレームに格納する方法 (2)

前回,read.table()とscan()を比較したんですが,もう少しきちんと調べてみると,実はread.tableパッケージというものがあるということを知りました.さらにstackoverflowにドンピシャのスレッドを見つけたので,これを実際に確かめてみました.

freadの検証

data.tableパッケージが高速なテーブルデータの読み込みをおこなうためのパッケージで,中でもfreadが最もパフォーマンスが高いようです.

##    user  system elapsed  Method
##   24.71    0.15   25.42  read.csv (first time)
##   17.85    0.07   17.98  read.csv (second time)
##   10.20    0.03   10.32  Optimized read.table
##    3.12    0.01    3.22  fread
##   12.49    0.09   12.69  sqldf
##   10.21    0.47   10.73  sqldf on SO
##   10.85    0.10   10.99  ffdf

via import - Quickly reading very large tables as dataframes in R - Stack Overflow

ということで,下記のようなコードで検証してみました.system.time()で処理に要した時間が測れます.

install.packages("data.table")
library(data.table)
require(data.table)
system.time(data <- fread("~/Documents/tmp/sample_20000000.dat"))
system.time(class(data) <- "data.frame")
system.time(names(data) <- c("uid", "sex", "age"))

結果

159.134 + 0.352 + 9.237 = 168.723秒ということで,先ほどと比べて相当に読み込み時間が短縮されました.まぁ,下記の結果をみる限り,もっとも効果があったのは,data.frame()を使わなかったためなのですが...

> system.time(data <- fread("~/Documents/tmp/sample_20000000.dat"))
   user  system elapsed 
153.813   1.776 159.134 
> system.time(class(data) <- "data.frame")
   user  system elapsed 
  0.196   0.156   0.352 
> system.time(names(data) <- c("uid", "sex", "age"))
   user  system elapsed 
  8.979   0.258   9.237 

以上,freadで読み込んで,classとnamesだけ変えてデータフレームにするのが一番効率的みたいですね.

ちなみに

前回のscan()を同じように処理してみたら,freadの1.5倍以上時間がかかっていたみたいですね.やはりscanよりもさらにfreadのほうが断然良いみたいです.そしてscanではあくまでリストでの読み込みでしかないので,classとnameの変換をしても,正しく処理されてくれませんでした.なので,data.frame()にかかる時間を考えると,なおさらfread一択っぽいですね.

> system.time(data <- scan("/Users/smrmkt/Documents/tmp/sample_20000000.dat",
+             list(user_id="", sex="", age=0)))
Read 20000000 records
   user  system elapsed 
287.967   3.085 291.143