27
14.07.02 Kashiwa.R #10 巨巨巨巨巨巨巨巨巨巨 data.table 巨巨巨巨 @yuifu

巨大な表を高速に扱うData.table について

Embed Size (px)

Citation preview

Page 1: 巨大な表を高速に扱うData.table について

14.07.02 Kashiwa.R #10

巨大な表を高速に扱うdata.table について

@yuifu

Page 2: 巨大な表を高速に扱うData.table について

自己紹介• @yuifu

• 大学院生

• バイオインフォマティクス

http://www.slideshare.net/yuifu/fdr-kashiwar-3

Page 3: 巨大な表を高速に扱うData.table について

data.table を紹介するスライドはすでに色々ありますが…

http://www.slideshare.net/sfchaos/datatable

(簡潔で分かりやすかったです)

Page 4: 巨大な表を高速に扱うData.table について

でも、 data.table さんって data.frame さんとかなり違うの…

• data.frame で当たり前だと思ってたことが、当たり前じゃなかったり…

• そこで本発表では

• data.table を使おうとしたら data.frameと色々違ってて面倒だった点に重点を置いて紹介する

Page 5: 巨大な表を高速に扱うData.table について

• データ解析でよく使われる

• 理解しやすい

イントロ

Page 6: 巨大な表を高速に扱うData.table について

表には 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 について

data.frame さんはちょっと…• data.frame で巨大な表を読み込むと…

• 読み込みが遅い• いちいち動作が重い• うっかり全行表示してしまうと辛い(固まる)

イントロ

Page 8: 巨大な表を高速に扱うData.table について

遅くても待てばいい?

• ルーチンの作業を実行するならそうかもしれない

• データ解析だとルーチンでない作業が多い

• データ読み込んだり

• 加工したり

• 層別したり

• 集計したり

• →  対話的にデータをいじくるには速いに越したことはない

イントロ

Page 9: 巨大な表を高速に扱うData.table について

そこで data.table

• 速い!

• 便利!

• うっかり全行表示しない!

http://photozou.jp/photo/show/1934405/188750786

イントロ

Page 10: 巨大な表を高速に扱うData.table について

表の作成が速い

> 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 について

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 について

表の読み込みが速い

> 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 について

全行表示しない

> 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 について

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 について

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 について

[ ] の中の扱いが違う

• data.frame では、行と列の数字を入れる

> dt[i, j, ]

expression をいれる

key をいれる その他の引数を入れる

data.tableの使い方

Page 17: 巨大な表を高速に扱うData.table について

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 について

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 について

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 について

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 について

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 について

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 について

メモリ消費量はほぼ同じ

> 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 について

実用例応用例

> 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 について

実用例応用例

> 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 について

まとめ

• 巨大な表は data.table で扱いましょう

Page 27: 巨大な表を高速に扱うData.table について

参考文献

• CRAN の data.table パッケージのページ

• http://cran.r-project.org/web/packages/data.table/index.html

• 英語で詳しく書いてある

• R 言語上級ハンドブック

• 日本語で詳しく書いてある