読者です 読者をやめる 読者になる 読者になる

INPUTしたらOUTPUT!

忘れっぽいんでメモっとく

ff packageの使い方

R

仕事でffを使用する機会があったので忘れる前にメモしとく。

使い方は以下を参考にさせて頂いた。


一時ディレクトリの指定

RのffとbigmemoryとRevoScaleRとを比較してみた

実体はテンポラリファイル内に大量に生成される

とあるようにデフォルトだと/tmp/Rtmp******とかいうディレクトリが都度作成される。

/配下に十分な空き領域がない場合は以下のコマンドでtmpディレクトリを変更する。

> options(fftempdir="/data/fftmp")


ファイルの読み込み

CSVファイルからffdfオブジェクトにデータを読み込むには次のようにする。

> air.ff <- read.csv.ffdf(file="2008.csv", header=TRUE)


RのffでGLMしてみたけど...

factor型にしたい列は読み込みの段階でfactor化しちゃうこと

とあるのでFactor型の変数がある場合は注意する。

ffオブジェクトの保存と読み込み

RのffとbigmemoryとRevoScaleRとを比較してみたにはffsaveとffloadが紹介されているがsave.ffdfとload.ffdfもある。save.ffdfだと指定したディレクトリに列毎の*.ffファイルが作成される。

> save.ffdf(air.ff, dir="/data/ffdat/air2008")


読込むときは次のようにする。

> ls()
[1] "air.ff"
> rm(air.ff)
> ls()
character(0)
> load.ffdf("/data/ffdat/air2008")
> ls()
[1] "air.ff"

save.ffdf/load.ffdfしか使っていないけど不安定なのでffsave/ffloadの方が良いかもしれない。

インデックスの取得と値の設定

欠損値を0埋めするような場合、通常のdata.frameだと

> air.df$ActualElapsedTime[is.na(air.df$ActualElapsedTime)] <- 0

のように書けば済むけどffdfだと次のようなエラーが発生する。

> air.ff$ActualElapsedTime[is.na(air.ff$ActualElapsedTime)] <- 0
Error: vmode(value) == v is not TRUE


これを避けるには条件を満たす行の数と同じ長さのffvectorを作成して代入する必要がある。(もっとスマートな方法があったらご教示ください)

> idx <- ffwhich(air.ff, is.na(ActualElapsedTime))
> air.ff$ActualElapsedTime[idx] <- ff(0, length=length(idx), vmode=vmode(air.ff$ActualElapsedTime))


オブジェクトのコピー

以下のようにload.ffdfで読込んだffdfオブジェクトから列を指定し別のオブジェクトを作成して保存すると、指定した列の*.ffファイルが元のディレクトリから消えてしまう。

> load.ffdf("/data/ffdat/air2008")
> air.ff.glm <- ffdf(
+ Year=air.ff$Year,
+ Month=air.ff$Month,
+ DayOfWeek=air.ff$DayOfWeek,
+ UniqueCarrier=air.ff$UniqueCarrier,
+ CRSElapsedTime=air.ff$CRSElapsedTime,
+ Origin=air.ff$Origin,
+ Dest=air.ff$Dest,
+ Distance=air.ff$Distance,
+ Cancelled=air.ff$Cancelled)
> save.ffdf(air.ff.glm, dir="/data/ffdat/air_glm2008")

これを避けるにはclone()を使用する。

> load.ffdf("/data/ffdat/air2008")
> air.ff.glm <- ffdf(
+ Year=clone(air.ff$Year),
+ Month=clone(air.ff$Month),
+ DayOfWeek=clone(air.ff$DayOfWeek),
+ UniqueCarrier=clone(air.ff$UniqueCarrier),
+ CRSElapsedTime=clone(air.ff$CRSElapsedTime),
+ Origin=clone(air.ff$Origin),
+ Dest=clone(air.ff$Dest),
+ Distance=clone(air.ff$Distance),
+ Cancelled=clone(air.ff$Cancelled))
> save.ffdf(air.ff.glm, dir="/data/ffdat/air_glm2008")


変数の指定の仕方

RのffでGLMしてみたけど...

dio.ffdf$xはff型で返ってくるから大丈夫
dio.ffdf[, 1]はオンメモリ(通常のvector)で返ってくるから爆死

とあるように同じ変数でも指定の仕方によって動作が異なる。hist()で痛い目みたのでメモしとく。

ff型でhist()

> air.hist <- hist(air.ff$ActualElapsedTime[!is.na(air.ff$ActualElapsedTime)])
> air.hist$breaks
  [1]   12.00   25.67   39.34   53.01   66.68   80.35   94.02  107.69  121.36  135.03  148.70  162.37
 [13]  176.04  189.71  203.38  217.05  230.72  244.39  258.06  271.73  285.40  299.07  312.74  326.41
 [25]  340.08  353.75  367.42  381.09  394.76  408.43  422.10  435.77  449.44  463.11  476.78  490.45
 [37]  504.12  517.79  531.46  545.13  558.80  572.47  586.14  599.81  613.48  627.15  640.82  654.49
 [49]  668.16  681.83  695.50  709.17  722.84  736.51  750.18  763.85  777.52  791.19  804.86  818.53
 [61]  832.20  845.87  859.54  873.21  886.88  900.55  914.22  927.89  941.56  955.23  968.90  982.57
 [73]  996.24 1009.91 1023.58 1037.25 1050.92 1064.59 1078.26 1091.93 1105.60 1119.27 1132.94 1146.61
 [85] 1160.28 1173.95 1187.62 1201.29 1214.96 1228.63 1242.30 1255.97 1269.64 1283.31 1296.98 1310.65
 [97] 1324.32 1337.99 1351.66 1365.33 1379.00

f:id:tak95:20140130182616p:plain

区間配列が細かく小数になってる。かつ欠損があるとエラーになる。

vectorでhist()

> which(names(air.ff)=="ActualElapsedTime")
[1] 12
> air.hist <- hist(air.ff[, 12])
> air.hist$breaks
 [1]    0   50  100  150  200  250  300  350  400  450  500  550  600  650  700  750  800  850  900  950
[21] 1000 1050 1100 1150 1200 1250 1300 1350 1400

f:id:tak95:20140130182628p:plain

こちらはdata.frameで実行するのと変わらない。欠損があってもエラーにならない。