2017-04-10 19 views
1

data.frameのシーケンスを頻繁に(各回の何百万回)サブセット化する必要があります。 data.frameは、およそ200行×30列のサイズです。状態に応じて、data.frameの値は1つの反復から次の反復に変化します。したがって、最初に1つのサブセットを実行することは機能しません。質問とは対照的に小さなデータのサブセットを高速化する方法がありますか。

when a data.table starts to be faster than a data.frame、私はdata.frameが最速であると思われることを、次の最小再現性の例が示すdata.frame/data.table

の与えられた大きさのためのサブセット化のスピードアップを探しています:

library(data.table) 
nmax <- 1e2 # for 1e7 the results look as expected: data.table is really fast! 
set.seed(1) 
x<-runif(nmax,min=0,max=10) 
y<-runif(nmax,min=0,max=10) 
DF<-data.frame(x,y) 
DT<-data.table(x,y) 

summary(microbenchmark::microbenchmark(
    setkey(DT,x,y), 
    times = 10L, unit = "us")) 

#    expr min  lq mean median  uq  max neval 
# 1 setkey(DT, x, y) 70.326 72.606 105.032 80.3985 126.586 212.877 10 

summary(microbenchmark::microbenchmark(
    DF[DF$x>5, ], 
    `[.data.frame`(DT,DT$x < 5,), 
    DT[x>5], 
    times = 100L, unit = "us")) 
#        expr  min  lq  mean median  uq  max neval 
# 1     DF[DF$x > 5, ] 41.815 45.426 52.40197 49.9885 57.4010 82.110 100 
# 2 `[.data.frame`(DT, DT$x < 5,) 43.716 47.707 58.06979 53.5995 61.2020 147.873 100 
# 3      DT[x > 5] 205.273 214.777 233.09221 222.0000 231.6935 900.164 100 

パフォーマンスを向上させるためにできることはありますか?

編集入力後:

  • 私は、離散イベントシミュレーションを実行していますし、各イベントのために、私は(私はそれがdata.framedata.tableであるかどうかを気にしない)リストで検索する必要があります。おそらく、私は別のアプローチを実装することができますが、3年以上にわたって開発されたコードを書き直さなければなりません。現時点では、これは選択肢ではありません。しかし、それを早くする方法がなければ、これは将来の選択肢になるかもしれません。
  • 技術的には、それはdata.framesのシーケンスではなく、ただ1つのdata.frameの1つで、繰り返しごとに変化します。しかし、これは「サブセットをもっと速くする方法」には影響しません。そして、その質問がより包括的であることを願っています。
+0

データの実質的にランダムな選択をサブセット化しない限り、同じ方法でデータフレームを繰り返しリピートするのではなく、参照できる既存のサブセットのリストを作成することができますか? –

+1

data.tableのサブセット化に伴うオーバーヘッドがあります。 http://stackoverflow.com/a/20179189/1412059 – Roland

+4

実際の問題について適切な質問をする必要があります。何百万回もdata.framesをサブセット化する場合、あなたのアプローチは間違っています。 – Roland

答えて

1

あなたは行列に変換するによるパフォーマンスの向上が表示されます。これはあなたのdata.frameの内容全体が数値である(またはあまりにも多くの問題を起こさずに変換できる)場合、実行可能な選択肢です。

ここに移動します。あなたがして、あなたのユースケースが複数回にデータを照会することが含まれる場合

summary(microbenchmark::microbenchmark(
    DM[DM[, 'x']>5, ], # # # # Quickest 
    as.matrix(DF)[DF$x>5, ], # # # # Still quicker with conversion 
    DF[DF$x>5, ], 
    `[.data.frame`(DT,DT$x < 5,), 
    DT[x>5], 
    times = 100L, unit = "us")) 

#        expr  min  lq  mean median  uq  max neval 
# 1   DM[DM[, "x"] > 5, ] 13.883 19.8700 22.65164 22.4600 24.9100 41.107 100 
# 2  as.matrix(DF)[DF$x > 5, ] 141.100 181.9140 196.02329 195.7040 210.2795 304.989 100 
# 3     DF[DF$x > 5, ] 198.846 238.8085 260.07793 255.6265 278.4080 377.982 100 
# 4 `[.data.frame`(DT, DT$x < 5,) 212.342 268.2945 346.87836 289.5885 304.2525 5894.712 100 
# 5      DT[x > 5] 322.695 396.3675 465.19192 428.6370 457.9100 4186.487 100 

library(data.table) 
nmax = 200 
cmax = 30 
set.seed(1) 
x<-runif(nmax,min=0,max=10) 
DF = data.frame(x) 
for (i in 2:cmax) { 
    DF = cbind(DF, runif(nmax,min=0,max=10)) 
    colnames(DF)[ncol(DF)] = paste0('x',i) 
} 
DT = data.table(DF) 
DM = as.matrix(DF) # # # or data.matrix(DF) if you have factors 

かつ迅速から遅いものまでランク付けし、比較、まず私はサイズ200x30でそれを持っているデータを修正しました変換を1回だけ行うことができ、速度を1桁大きくすることができます。

+0

クール、私はすでに諦めましたが、いつも誰かが良いアイデアを持っているようです:-) – Christoph

関連する問題