RigelのR言語メモであーる(R言語だけとは言っていない)

RigelのR言語メモであーる(主にpython)

興味あることや趣味、やったことについて書くよ

Rでcsvの書き込みと読み込みの高速化

Rでcsvファイルの高速な書き込みと読み込みの方法。
よく使われているcsvの書き込みと読み込みの関数にwrite.csvとread.csvがある。
しかし、どちらの関数も実行時間が遅い。
私が良く使っている関数は、data.tableパッケージのfwriteとfreadです。
こっちの方が非常に高速。
では実際、実行時間にどれだけ差があるのだろう。
本記事では、それぞれの実行時間を比較する。  

write.csvとfwriteの比較①

データを作成してcsvとして書き込みその時間を比較する。
データは1000行1000列の行列(サイズは約2MB)を100ファイル。
fwriteはmatrixを出力できないのでdata.frameに変換する。
時間の計測にはsystem.timeを使う。

library(data.table)
nr=1000
nc=1000
N=100
#write.csvの計測
system.time(
  for(i in 1:N)
  {
    data=matrix(0,nrow=nr,ncol=nc)
    write.csv(data,"test.csv")
  }
)
#fwriteの計測
system.time(
  for(i in 1:N)
  {
    data=data.frame(matrix(0,nrow=nr,ncol=nc))
    fwrite(data,"test.csv")
  }
)

結果

ユーザ システム 経過
write.csv 63.262 1.294 67.953
fwrite 12.520 0.606 13.677

read.csvとfreadの比較①

次に作成したデータを読み込みその時間を比較する。

N=100
#read.csvの計測
system.time(
  for(i in 1:N)
  {
    data=read.csv("test.csv")
  }
)
#freadの計測
system.time(
  for(i in 1:N)
  {
    data=fread("test.csv")
  }
)

結果

ユーザ システム 経過
read.csv 40.435 0.699 41.940
fread 4.631 0.094 4.743

write.csvとfwriteの比較②

データのサイズを変えてみる。
10000行10000列の行列(サイズは約200MB)を1ファイル。

library(data.table)
nr=10000
nc=10000
N=1
#write.csvの計測
system.time(
  for(i in 1:N)
  {
    data=matrix(0,nrow=nr,ncol=nc)
    write.csv(data,"test.csv")
  }
)
#fwriteの計測
system.time(
  for(i in 1:N)
  {
    data=data.frame(matrix(0,nrow=nr,ncol=nc))
    fwrite(data,"test.csv")
  }
)

結果

ユーザ システム 経過
write.csv 74.812 1.702 79.110
fwrite 10.129 1.656 8.006

read.csvとfreadの比較②

再び作成したデータを読み込みその時間を比較する。

N=1
#read.csvの計測
system.time(
  for(i in 1:N)
  {
    data=read.csv("test.csv")
  }
)
#freadの計測
system.time(
  for(i in 1:N)
  {
    data=fread("test.csv")
  }
)

結果

ユーザ システム 経過
read.csv 46.540 1.825 49.908
fread 4.920 0.187 5.295

まとめ

2パターンで試したが、どちらのパターンでもwrite.csv、read.csvとfwrite、freadとの間に、明らかな実行時間の差があった。
差が小さい時では約5倍、大きい時では約10倍。
本当は何回か実験するべきだろうけど、これだけ差があることがわかれば何回もする必要はない。なにより面倒。
fwriteとfreadの方が明らかに早いが、注意点もある。
fwriteが出力できる型はdata.frameとdata.tableであり、matrixは出力できない。
freadはデフォルトではdata.table型で読み込むのでdata.frame型で読み込むなら、引数にdata.table=Fとする必要がある。
data.table型については、以下のリンクを参照。
qiita.com