Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

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

6.939 visualizaciones

Publicado el

Publicado en: Datos y análisis
  • Sé el primero en comentar

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

  1. 1. 14.07.02 Kashiwa.R #10 巨大な表を高速に扱う data.table について @yuifu
  2. 2. 自己紹介 • @yuifu • 大学院生 • バイオインフォマティクス 2 http://www.slideshare.net/yuifu/fdr-kashiwar-3
  3. 3. data.tableを紹介するスライドはすでに色々ありますが… 3 http://www.slideshare.net/sfchaos/datatable (簡潔で分かりやすかったです )
  4. 4. でも、data.tableさんってdata.frameさんとかなり違うの… • data.frameで当たり前だと思ってたことが、当たり前じゃなか ったり… • そこで本発表では • data.tableを使おうとしたらdata.frameと色々違ってて面倒 だった点に重点を置いて紹介する 4
  5. 5. 表 • データ解析でよく使われる • 理解しやすい 7 イントロ
  6. 6. 表にはdata.frameがよく使われる • 外部の表形式データをread.table, read.csvで読み込んだり… • Rに用意されてるデータセットもたいていdata.frame 8 > class(USArrests) [1] "data.frame" > head(USArrests) Murder Assault UrbanPop Rape Alabama 13.2 236 58 21.2 Alaska 10.0 263 48 44.5 Arizona 8.1 294 80 31.0 Arkansas 8.8 190 50 19.5 California 9.0 276 91 40.6 Colorado 7.9 204 78 38.7 イントロ
  7. 7. data.frameさんはちょっと… • data.frameで巨大な表を読み込むと… • 読み込みが遅い • いちいち動作が重い • うっかり全行表示してしまうと辛い(固まる) 9 イントロ
  8. 8. 遅くても待てばいい? • ルーチンの作業を実行するならそうかもしれない • データ解析だとルーチンでない作業が多い • データ読み込んだり • 加工したり • 層別したり • 集計したり • → 対話的にデータをいじくるには速いに越したことはない 10 イントロ
  9. 9. そこでdata.table • 速い! • 便利! • うっかり全行表示しない! 11 http://photozou.jp/photo/show/1934405/188750786 イントロ
  10. 10. 表の作成が速い 14 > 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 v 1 A a 0.5229118 2 A a 0.8970509 3 A a 0.6302130 4 A a 0.5424760 5 A a 0.2111072 6 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 v 1: A a 0.4385627 2: A a 0.6508053 3: A a 0.7925830 4: A a 0.4220287 5: A a 0.8465619 6: A a 0.5719564 data.frame data.table data.tableの方が表の作成が速い! data.tableの使い方
  11. 11. data.frameをdata.tableに変換 15 > dt_car <- data.table(cars) > head(dt_car) speed dist 1: 4 2 2: 4 10 3: 7 4 4: 7 22 5: 8 16 6: 9 10 data.tableの使い方
  12. 12. 表の読み込みが速い 16 > 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の使い方
  13. 13. 全行表示しない 17 > dim(DT) [1] 100000004 3 > DT x y v 1e+00: A a 0.4385627 2e+00: A a 0.6508053 3e+00: A a 0.7925830 4e+00: A a 0.4220287 5e+00: A a 0.8465619 --- 1e+08: Z z 0.2710513 1e+08: Z z 0.1001215 1e+08: Z z 0.7190453 1e+08: Z z 0.3677681 1e+08: Z z 0.4660653 data.tableの使い方 うっかり全行表示しようとしない! →安心!
  14. 14. tables()でメモリ上にあるdata.tableオブジェクトを確認 18 > 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の使い方
  15. 15. data.frameのようには要素にアクセスできない例 19 > dt method V2 platform source V5 V6 year 1: - - - - - - 2009 2: - - - - - - 2009 3: - - - - - - 2009 4: - - - - - - 2009 5: - - - - - - 2009 --- 773038: WGS Other unspecified GENOMIC - - 2012 773039: WGS Other unspecified GENOMIC - - 2012 773040: WGS Other unspecified GENOMIC - - 2012 773041: WGS Other unspecified GENOMIC - - 2012 773042: WGS Other unspecified GENOMIC - - 2012 > dt[1,] method V2 platform source V5 V6 year 1: - - - - - - 2009 > dt[1,3] [1] 3 > dt[,3] [1] 3 data.tableの使い方
  16. 16. [ ] の中の扱いが違う • data.frameでは、行と列の数字を入れる 20 > dt[i, j, ] expressionをいれる keyをいれる その他の引数を入れる data.tableの使い方
  17. 17. i: 行へのアクセス 21 > dt x v 1: b -1.07907245 2: b 0.92515170 3: b -0.02339863 4: a 2.06498547 5: a -1.03080796 > dt[2,] x v 1: b 0.9251517 > dt[dt$x=="b",] x v 1: b -1.07907245 2: b 0.92515170 3: 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の使い方
  18. 18. i: キーによる行へのアクセス 22 > 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 v 1: b -1.07907245 2: b 0.92515170 3: b -0.02339863 data.tableの使い方
  19. 19. i: キーによる行へのアクセスは速い 23 > 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の使い方
  20. 20. j: 集計する(例) 24 > 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 1922727 10: J 1922573 11: K 1922276 12: L 1922843 13: M 1922837 14: N 1923137 15: O 1922958 16: P 1923937 17: Q 1922784 18: R 1923248 19: S 1922781 20: T 1922965 21: U 1924161 22: V 1922554 23: W 1923009 24: X 1922651 25: Y 1922543 26: 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より速い!
  21. 21. j: expressionを入れる 25 > 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の使い方
  22. 22. data.frameとdata.table 26 data.tableの使い方 タスク data.table data.frame 表の作成 data.table data.frame 表の読み込み fread read.table 行の名前の設定 setkey rowname 列の名前の設定 setnames colnames 複数の表の結合 rbindlist cbind rbind cbind 列の追加 := cbind data.frame 名前・発想が違うものについて
  23. 23. メモリ消費量はほぼ同じ 27 > 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つの列(変数)をキーに設定した後 速いのに、メモリ消費量はほぼ同じ! キーを設定した後でも、メモリ消費量はほぼ同じ!
  24. 24. 実用例 34 応用例 > 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は?
  25. 25. 実用例 35 応用例 > library(ggplot2) > g <- ggplot(data.table(dat), aes(x=year, y=V1)) + + geom_bar(stat = "identity") + + facet_wrap(~ platform) + + xlim(2008,2013) > print(g)
  26. 26. まとめ • 巨大な表はdata.tableで扱いましょう 36
  27. 27. 参考文献 • CRANのdata.tableパッケージのページ • http://cran.r-project.org/web/packages/data.table/index.html • 英語で詳しく書いてある • R言語上級ハンドブック • 日本語で詳しく書いてある 37

×