Download - 巨大な表を高速に扱うData.table について
![Page 1: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/1.jpg)
14.07.02 Kashiwa.R #10
巨大な表を高速に扱うdata.table について
@yuifu
![Page 2: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/2.jpg)
自己紹介• @yuifu
• 大学院生
• バイオインフォマティクス
http://www.slideshare.net/yuifu/fdr-kashiwar-3
![Page 3: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/3.jpg)
data.table を紹介するスライドはすでに色々ありますが…
http://www.slideshare.net/sfchaos/datatable
(簡潔で分かりやすかったです)
![Page 4: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/4.jpg)
でも、 data.table さんって data.frame さんとかなり違うの…
• data.frame で当たり前だと思ってたことが、当たり前じゃなかったり…
• そこで本発表では
• data.table を使おうとしたら data.frameと色々違ってて面倒だった点に重点を置いて紹介する
![Page 5: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/5.jpg)
表
• データ解析でよく使われる
• 理解しやすい
イントロ
![Page 6: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/6.jpg)
表には data.frame がよく使われる• 外部の表形式データを read.table, read.csv で読み込んだり
…
• R に用意されてるデータセットもたいてい data.frame
> class(USArrests)[1] "data.frame"> head(USArrests) Murder Assault UrbanPop RapeAlabama 13.2 236 58 21.2Alaska 10.0 263 48 44.5Arizona 8.1 294 80 31.0Arkansas 8.8 190 50 19.5California 9.0 276 91 40.6Colorado 7.9 204 78 38.7
イントロ
![Page 7: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/7.jpg)
data.frame さんはちょっと…• data.frame で巨大な表を読み込むと…
• 読み込みが遅い• いちいち動作が重い• うっかり全行表示してしまうと辛い(固まる)
イントロ
![Page 8: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/8.jpg)
遅くても待てばいい?
• ルーチンの作業を実行するならそうかもしれない
• データ解析だとルーチンでない作業が多い
• データ読み込んだり
• 加工したり
• 層別したり
• 集計したり
• → 対話的にデータをいじくるには速いに越したことはない
イントロ
![Page 9: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/9.jpg)
そこで data.table
• 速い!
• 便利!
• うっかり全行表示しない!
http://photozou.jp/photo/show/1934405/188750786
イントロ
![Page 10: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/10.jpg)
表の作成が速い
> grpsize = ceiling(1e8/26^2)> tt=system.time( DF <- data.frame(+ x=rep(LETTERS,each=26*grpsize),+ y=rep(letters,each=grpsize),+ v=runif(grpsize*26^2),+ stringsAsFactors=FALSE) + )> tt ユーザ システム 経過 18.319 9.352 35.238
> head(DF) x y v1 A a 0.52291182 A a 0.89705093 A a 0.63021304 A a 0.54247605 A a 0.21110726 A a 0.6619162
> grpsize = ceiling(1e8/26^2)> tt=system.time( DT <- data.table(+ x=rep(LETTERS,each=26*grpsize),+ y=rep(letters,each=grpsize),+ v=runif(grpsize*26^2)) + )> tt ユーザ システム 経過 6.866 0.980 8.787
> head(DT) x y v1: A a 0.43856272: A a 0.65080533: A a 0.79258304: A a 0.42202875: A a 0.84656196: A a 0.5719564
data.frame data.table
data.table の方が表の作成が速い!
data.tableの使い方
![Page 11: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/11.jpg)
data.frame を data.table に変換
> dt_car <- data.table(cars)> head(dt_car) speed dist1: 4 22: 4 103: 7 44: 7 225: 8 166: 9 10
data.tableの使い方
![Page 12: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/12.jpg)
表の読み込みが速い
> system.time(df <- read.table(filename, sep="\t", fill=T)) ユーザ システム 経過 7.472 0.176 7.738
> dim(df)[1] 626393 7
> system.time(dt <- fread(filename, sep="\t")) ユーザ システム 経過 0.387 0.028 0.416
> dim(dt)[1] 773042 7
data.frame data.table
data.table の方が表の読み込みが速い!
data.tableの使い方
![Page 13: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/13.jpg)
全行表示しない
> dim(DT)[1] 100000004 3
> DT x y v1e+00: A a 0.43856272e+00: A a 0.65080533e+00: A a 0.79258304e+00: A a 0.42202875e+00: A a 0.8465619 --- 1e+08: Z z 0.27105131e+08: Z z 0.10012151e+08: Z z 0.71904531e+08: Z z 0.36776811e+08: Z z 0.4660653
data.tableの使い方
うっかり全行表示しようとしない!→ 安心!
![Page 14: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/14.jpg)
tables() でメモリ上にある data.table オブジェクトを確認
> tables() NAME NROW MB COLS KEY [1,] ans2 147,929 4 x,y,v [2,] ans3 147,929 4 x,y,v x,y [3,] dt 773,042 40 method,V2,platform,source,V5,V6,year platform,method[4,] DT 100,000,004 2289 x,y,v x,y [5,] dt_car 50 1 speed,dist [6,] ss 26 1 x,V1 x Total: 2,339MB
data.tableの使い方
![Page 15: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/15.jpg)
data.frame のようには要素にアクセスできない例
> dt method V2 platform source V5 V6 year 1: - - - - - - 2009 2: - - - - - - 2009 3: - - - - - - 2009 4: - - - - - - 2009 5: - - - - - - 2009 --- 773038: WGS Other unspecified GENOMIC - - 2012773039: WGS Other unspecified GENOMIC - - 2012773040: WGS Other unspecified GENOMIC - - 2012773041: WGS Other unspecified GENOMIC - - 2012773042: WGS Other unspecified GENOMIC - - 2012> dt[1,] method V2 platform source V5 V6 year1: - - - - - - 2009> dt[1,3][1] 3> dt[,3][1] 3
data.tableの使い方
![Page 16: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/16.jpg)
[ ] の中の扱いが違う
• data.frame では、行と列の数字を入れる
> dt[i, j, ]
expression をいれる
key をいれる その他の引数を入れる
data.tableの使い方
![Page 17: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/17.jpg)
i: 行へのアクセス
> dt x v1: b -1.079072452: b 0.925151703: b -0.023398634: a 2.064985475: a -1.03080796> dt[2,] x v1: b 0.9251517> dt[dt$x=="b",] x v1: b -1.079072452: b 0.925151703: b -0.02339863> dt["b",] 以下にエラー `[.data.table`(dt, "b", ) : When i is a data.table (or character vector), x must be keyed (i.e. sorted, and, marked as sorted) so data.table knows which columns to join to and take advantage of x being sorted. Call setkey(x,...) first, see ?setkey.
data.tableの使い方
![Page 18: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/18.jpg)
i: キーによる行へのアクセス> setkey(dt, x)> tables() NAME NROW MB COLS KEY[1,] dt 5 1 x,v x [2,] dt_car 50 1 speed,dist Total: 2MB> dt["b",] x v1: b -1.079072452: b 0.925151703: b -0.02339863
data.tableの使い方
![Page 19: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/19.jpg)
i: キーによる行へのアクセスは速い
> tt=system.time(+ ans1 <- DF[DF$x=="R" & DF$y=="h",])> tt ユーザ システム 経過 15.840 1.042 17.046
> tt=system.time(ans2 <- DT[DT$x=="R" & DT$y=="h",])> tt ユーザ システム 経過 6.756 0.368 7.124
data.frame data.table
> system.time(setkey(DT, x, y)) ユーザ システム 経過 0.688 0.178 0.871 > system.time(ans3 <- DT[J("R","h")]) ユーザ システム 経過 0.006 0.002 0.009
ベクトルを先頭からスキャンする場合
キーを設定し、二分探索を行う場合
キーを設定した方が速い!
data.tableの使い方
![Page 20: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/20.jpg)
j: 集計する(例)
> DT[,sum(v)][1] 49994142
data.tableの使い方
> DT[,sum(v),by=x] x V1 1: A 1922034 2: B 1922008 3: C 1923013 4: D 1922349 5: E 1922904 6: F 1923302 7: G 1922370 8: H 1923551 9: I 192272710: J 192257311: K 192227612: L 192284313: M 192283714: N 192313715: O 192295816: P 192393717: Q 192278418: R 192324819: S 192278120: T 192296521: U 192416122: V 192255423: W 192300924: X 192265125: Y 192254326: Z 1922629 x V1
by で列名を指定すると指定した変数の値により行をグループ分けした上でsum(v) を行う
sum(v) を行う
j の位置では、列名は引用符で囲まない
> system.time(tt <- tapply(DT$v,DT$x,sum)) ユーザ システム 経過 35.287 14.561 56.807 > system.time(ss <- DT[,sum(v),by=x]) ユーザ システム 経過 1.704 0.441 2.395
tapply より速い!
![Page 21: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/21.jpg)
j: expression を入れる
> dt_car[, plot(speed, dist)]NULL
> dt_car[, dist/speed] [1] 0.5000000 2.5000000 0.5714286 3.1428571 2.0000000 1.1111111 1.8000000 2.6000000 3.4000000 1.5454545[11] 2.5454545 1.1666667 1.6666667 2.0000000 2.3333333 2.0000000 2.6153846 2.6153846 3.5384615 1.8571429[21] 2.5714286 4.2857143 5.7142857 1.3333333 1.7333333 3.6000000 2.0000000 2.5000000 1.8823529 2.3529412[31] 2.9411765 2.3333333 3.1111111 4.2222222 4.6666667 1.8947368 2.4210526 3.5789474 1.6000000 2.4000000[41] 2.6000000 2.8000000 3.2000000 3.0000000 2.3478261 2.9166667 3.8333333 3.8750000 5.0000000 3.4000000
変数同士の計算ができたり
別の関数を実行したり
data.tableの使い方
![Page 22: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/22.jpg)
data.frame と data.tabledata.tableの使い方
タスク data.table data.frame
表の作成 data.table data.frame
表の読み込み fread read.table
行の名前の設定 setkey rowname
列の名前の設定 setnames colnames
複数の表の結合 rbindlistcbind
rbindcbind
列の追加 :=cbind
data.frame
名前・発想が違うものについて
![Page 23: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/23.jpg)
メモリ消費量はほぼ同じ
> dim(DF)[1] 100000004 3> object.size(DF)2400003488 bytes
> dim(DT)[1] 100000004 3> object.size(DT)2400004008 bytes
data.frame data.table
> system.time(setkey(DT, x, y)) ユーザ システム 経過 0.817 0.228 1.049 > object.size(DT)2400004272 bytes
10 億行 × 3列の表の場合
2つの列(変数)をキーに設定した後
速いのに、メモリ消費量はほぼ同じ!キーを設定した後でも、メモリ消費量はほぼ同じ!
![Page 24: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/24.jpg)
実用例応用例
> dt <- fread("sra.list", sep=“\t")> setnames(dt, "V3", "platform")> setnames(dt, "V7", "year")> setnames(dt, "V1", "method")> setnames(dt, "V4", "source")> setkey(dt, source)> dat <- dt["GENOMIC", nrow(.SD), by=list(platform, source, year)]> dat <- dat[!grep("-|unsp", platform),]> library(ggplot2)> g <- ggplot(data.table(dat), aes(x=year, y=V1)) + + geom_bar(stat = "identity") ++ facet_wrap(~ platform) + + xlim(2008,2013) > print(g)
SRA で、 source がゲノム配列であるデータがよく読まれている platform は?
![Page 25: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/25.jpg)
実用例応用例
> library(ggplot2)> g <- ggplot(data.table(dat), aes(x=year, y=V1)) + + geom_bar(stat = "identity") ++ facet_wrap(~ platform) + + xlim(2008,2013) > print(g)
![Page 26: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/26.jpg)
まとめ
• 巨大な表は data.table で扱いましょう
![Page 27: 巨大な表を高速に扱うData.table について](https://reader034.vdocuments.pub/reader034/viewer/2022052507/558207b0d8b42aa9498b4f49/html5/thumbnails/27.jpg)
参考文献
• CRAN の data.table パッケージのページ
• http://cran.r-project.org/web/packages/data.table/index.html
• 英語で詳しく書いてある
• R 言語上級ハンドブック
• 日本語で詳しく書いてある