2012-03-26 6 views
5

目的は、データフレーム内の因子/文字列変数のインジケータを作成することです。そのデータフレームは> 2mmの行を持ち、ウィンドウでRを実行しているので、.parallel = Tでplyrを使用するオプションはありません。だから私はplyrとreshape2で "分割と征服"ルートを取っています。メルトキャストを実行大きなデータフレームでのインジケータの生成

は、メモリ不足、および

ddply(idata.frame(items) , c("ID") , function(x){ 
     ( colSums(model.matrix(~ x$element - 1)) > 0 ) 
} , .progress="text")  

または

ddply(idata.frame(items) , c("ID") , function(x){ 
      ( elements %in% x$element ) 
    } , .progress="text") 

を使用すると、しばらく時間がかかりません。最速のアプローチは、以下のtapplyへの呼び出しです。これをスピードアップする方法がありますか? %inステートメントは、model.matrix呼び出しよりも速く実行されます。ありがとう。

set.seed(123) 

dd <- data.frame(
    id = sample(1:5, size=10 , replace=T) , 
    prd = letters[sample(1:5, size=10 , replace=T)] 
) 

prds <- unique(dd$prd) 

tapply(dd$prd , dd$id , function(x) prds %in% x) 
+0

あなたの例では混乱しています。 'dd $ id'で' dd $ prd'を分割し、各idにどのprdsの値が含まれているかを確認しますが、 'prds'はソートされません(!)' prds < - sortユニークな(dd $ prd)) '(それは私にはもっと意味をなさないでしょう...)? –

+0

prdsで利用可能な要素に対応するインジケータ(論理)がIDを渡って同じ順序を持つ限り、ソート方法は関係ありません。 –

+0

OK。下の私の答えで私の他の質問を参照してください... –

答えて

4

。ここではもう少し野心的な例である:

library(bigmemory) 
library(bigtabulate) 

set.seed(123) 

dd <- data.frame(
    id = sample(1:15, size=2e6 , replace=T), 
    prd = letters[sample(1:15, size=2e6 , replace=T)] 
) 

prds <- unique(dd$prd) 

benchmark(
bigtable(dd,c(1,2))>0, 
table(dd[,1],dd[,2])>0, 
xtabs(~id+prd,data=dd)>0, 
tapply(dd$prd , dd$id , function(x) prds %in% x) 
) 

とベンチマークの結果は(私は新しいもののすべての時間を学んでいる):

          test replications elapsed relative user.self sys.self user.child sys.child 
1      bigtable(dd, c(1, 2)) > 0   100 54.401 1.000000 51.759 3.817   0   0 
2     table(dd[, 1], dd[, 2]) > 0   100 112.361 2.065422 107.526 6.614   0   0 
4 tapply(dd$prd, dd$id, function(x) prds %in% x)   100 178.308 3.277660 166.544 13.275   0   0 
3    xtabs(~id + prd, data = dd) > 0   100 229.435 4.217478 217.014 16.660   0   0 

をそして、それはかなりの量によって勝利bigtableを示しています。結果は、すべてのIDがすべてのIDに含まれているのとほぼ同じですが、結果の形式の詳細については、?bigtableを参照してください。

+0

ありがとうございました。 –

+0

実際のデータセット(!)で実行が完了しました(bigtableを使用)。 –

1

%in%機能の使用は、私には逆のようです。また、データの各行に対して真偽結果を必要とする場合は、ベクトル演算として%inを使用するか、aveを使用する必要があります。ここでは必要ではありませんが、すべての項目に適用する必要があるより複雑な関数がある場合は、この関数を使用することをお勧めします。

set.seed(123) 

dd <- data.frame(
    id = sample(1:5, size=10 , replace=T) , 
    prd = letters[sample(1:5, size=10 , replace=T)] 
) 

prds <- unique(dd$prd) 
target.prds <- prds[1:2] 
dd$prd.in.trgt <- with(dd, prd %in% target.prds) 
+0

'prds'(または' target.prds')と同じくらい多くのインジケータがあります: 'c(1,2,3)%%c(1)'はそのレコードに1が入っていることを示しますが、 2%も3%もありません。 –

+0

%で%を再定義するだけでは、それがそうでないものであるとは限りません。また、データフレームでは、すべての要素がローごとに通常のエントリ数を持つ必要があります。 TRUEとFALSEの論理行列、またはリストのいずれかが「ヒット」する場合は、可変数に対応するデータ構造を使用する必要があります。 –

+0

私はあなたが言っていることを理解しています。 '%in% 'の呼び出しは、常に同じ数の論理を返します。私は 'tapply'呼び出しで' function(x)unique(x $ prd) 'を使い始めました。それは不揃いな配列を生成していました。 –

2

は、あなたが十分な個人インジケータ行列あなたのために、その後、一定のレベルの数を保つならば、問題はレベルの番号等(IDは、の数の点をで拡張する方法をもう少し言うことができます再計算はすべてTRUE /すべて1に近づくでしょう...)?パッケージbigmemorybigtabulateはあなたの友人かもしれないが、この問題のために私はxtabsがより速くなるだろうと予想しますが、このサイズの例のためではないのです...

library(rbenchmark) 
benchmark(
      tapply(dd$prd , dd$id , function(x) prds %in% x), 
      xtabs(~id+prd,data=dd)>0) 

    test  replications elapsed relative 
1 tapply(...)    100 0.053 1.000000 
2 xtabs(...) > 0   100 0.120 2.264151 
+0

1350万のアイテムがあります(780,000個のIDにまたがるので、IDごとに複数のアイテムがあります)。prdには83の異なる要素があります。ちなみにrbenchmarkに注目してくれてありがとう。 –