[追記] 高速でデータを読み込む fread() 以外の選択肢としてHadley Wickhamの readr もお薦めです。現時点では fread() のほうが少し速いようです。
[2022年末追記] 2022年末、Rでcsvを読むという記事に最新事情が紹介されています。
data.table
は従来の data.frame
に代わるデータ型を提供するパッケージです。効率が良く,巨大なデータファイルの読み込み・書き出しが桁違いに速くなります。
インストールとライブラリの読み込みは想定通りです:
install.packages("data.table") library(data.table)
data.frame
の読み込みは read.csv()
などのいくつかの関数で行いましたが,data.table
の読み込みは fread()
だけです。
data = fread("ファイル名またはURL")
CSVかTSVか,ヘッダがあるかないかは,たいてい自動判断してくれます。もしうまくいかなかったら,オプションで指定します。
data = fread("ファイル名またはURLまたはデータ", sep=",", header=TRUE, na.strings=c("NA",""))
ただし,文字コードだけは設定できないようです。Mac上ではUTF-8しか扱ってくれませんでした。また,na.strings=c("","欠測値")
のようなUTF-8文字列を与えても無視されるようです。
Sys.setlocale(category="LC_ALL", locale="ja_JP.SJIS")
してみましたが,読み込み方は変わったものの,文字化けして表示されるだけのようです。
また,開発途上のためか高速化のためか,CSVはRFC 4180準拠ではなく,ダブルクォートが入り子になっているとうまくいきません。
おもしろい使い方として,data = fread("
まで打ってから,データをRコンソールにコピペし,")
を打ち込むという方法も使えます。例えば
data = fread("魔,方,陣 2,9,4 7,5,3 6,1,8")
または
data = fread(" 魔,方,陣 2,9,4 7,5,3 6,1,8 ")
のような感じです。これで data
と打ち込むと
魔 方 陣 1: 2 9 4 2: 7 5 3 3: 6 1 8
と表示されます。
現実的な例でやってみましょう。RgoogleMapsを使った放射線地図で使った福島県の放射線データ fukushima.csv は,422656地点の緯度(lat),経度(lon),放射線(radiation,μSv/h単位),日時(datetime)を収めたものです。これをローカルにダウンロードして,読み込んで,それぞれの欄の平均値を表示し,時間を計測してみましょう(使っているマシンが多少速くなったので,結果を改訂しました):
> # 従来のdata.frame版 > system.time({df = read.csv("~/public_html/stat/data/fukushima.csv", as.is=TRUE)}) ユーザ システム 経過 0.928 0.027 0.963 > system.time(print(mean(df$lat))) [1] 37.59176 ユーザ システム 経過 0.001 0.000 0.001 > system.time(print(mean(df$lon))) [1] 140.4282 ユーザ システム 経過 0.001 0.000 0.001 > system.time(print(mean(as.POSIXct(df$datetime)))) [1] "2011-07-18 01:52:49 JST" ユーザ システム 経過 7.881 3.178 11.147 > > # 新しいdata.table版 > system.time({dt = fread("~/public_html/stat/data/fukushima.csv")}) ユーザ システム 経過 0.174 0.022 0.057 > system.time(print(mean(dt$lat))) [1] 37.59176 ユーザ システム 経過 0.001 0.000 0.001 > system.time(print(mean(dt$lon))) [1] 140.4282 ユーザ システム 経過 0.001 0.000 0.001 > system.time(print(mean(as.POSIXct(dt$datetime)))) [1] "2011-07-18 01:52:49 JST" ユーザ システム 経過 7.890 3.093 11.059
読み込みは劇的に早くなりました。他の計算はあまり変わりません。ただ,この場合は,日時を表す文字列を内部形式に変換する as.POSIXct()
が遅すぎてどうにもなりません。
これを改善するには fasttime パッケージを使います。
install.packages("fasttime")
試してみましょう。
> library(fasttime) > > system.time(print(mean(fastPOSIXct(df$datetime)))) [1] "2011-07-18 10:52:49 JST" ユーザ システム 経過 0.022 0.001 0.024 > system.time(print(mean(fastPOSIXct(dt$datetime)))) [1] "2011-07-18 10:52:49 JST" ユーザ システム 経過 0.019 0.000 0.020
今のマシンでも2桁以上,昔のマシンでは3桁高速化できました! すごいですね! でも答えが違ってますね。実は fasttime は変換元の文字列はGMTにしか対応していないので,JSTなら 9*3600
を引く必要があります。
> mean(fastPOSIXct(dt$datetime)) - 9*3600 [1] "2011-07-18 01:52:49 JST"
data.table の fread()
と fasttime の fastPOSIXct()
で劇的に高速化できることがおわかりいただけたでしょうか。
まだまだ未完ですが,とりあえず data.table を使った例:
[追記] lubridateパッケージにも高速な変換関数があります:R で文字列を POSIX time に変換するには lubridate::parse_date_time2() がちょっぱや #rstatsj - Qiita
[追記] Hadley Wickham が fread()
に相当する readr というもの(旧 fastread)を作っています:hadley/readr · GitHub
[追記] readr がCRANに入りました(readr 0.1.0 | RStudio Blog)。SPSS,Stata,SASファイルを読む haven も。Excelファイルを読む readxl(RでExcelのデータを読む方法参照)も合わせて,Hadley Wickham だらけになりました。