13

私はフォームの単純なテーブルを扱っています

date         variable   value
1970-01-01   V1         0.434
1970-01-01   V2         12.12
1970-01-01   V3         921.1
1970-01-02   V1         -1.10
1970-01-03   V3         0.000
1970-01-03   V5         312e6
...          ...        ...

ペア (日付、変数) は一意です。このテーブルをワイドフォームに変換したいと思います。

date         V1         V2         V3         V4         V5        
1970-01-01   0.434      12.12      921.1      NA         NA
1970-01-02   -1.10      NA         NA         NA         NA
1970-01-03   0.000      NA         NA         NA         312e6

そして、1e6 レコードのテーブルに対して繰り返し操作を繰り返さなければならないので、可能な限り最速の方法でそれを実行したいと考えています。R ネイティブ モードではtapply()reshape()との両方d*ply()が によって速度的に支配されていると思いますdata.table。後者のパフォーマンスを sqlite ベースのソリューション (または他の DB) に対してテストしたいと思います。これは以前に行われたことがありますか?パフォーマンスの向上はありますか? また、「ワイド」フィールド (日付) の数が可変であり、事前にわかっていない場合、sqlite でトールをワイドに変換するにはどうすればよいでしょうか?

4

2 に答える 2

4

私は何をするかに基づいたアプローチを使用しますがtapply、約1桁高速です(主にセルごとの関数呼び出しがないため)。

tallPrasad の投稿から使用するタイミング:

pivot = function(col, row, value) {
  col = as.factor(col)
  row = as.factor(row)
  mat = array(dim = c(nlevels(row), nlevels(col)), dimnames = list(levels(row), levels(col)))
  mat[(as.integer(col) - 1L) * nlevels(row) + as.integer(row)] = value
  mat
}

> system.time( replicate(100, wide <- with(tall, tapply( value, list(dt,tkr), identity))))
   user  system elapsed 
  11.31    0.03   11.36 

> system.time( replicate(100, wide <- with(tall, pivot(tkr, dt, value))))
   user  system elapsed 
    0.9     0.0     0.9 

注文に関して考えられる問題については、問題はないはずです。

> a <- with(tall, pivot(tkr, dt, value))
> b <- with(tall[sample(nrow(tall)), ], pivot(tkr, dt, value))
> all.equal(a, b)
[1] TRUE
于 2011-03-15T13:51:01.290 に答える
1

いくつかの意見。いくつかのSOの質問は、Sql(ite)でトールからワイドへのピボットを実行する方法に対応しています:ここここ。私はそれらをあまり深く調べていませんが、SQLでそれを行うのは醜いです:あなたのSQLクエリはクエリで可能なすべてのキーを明示的に言及する必要があります!(私が間違っている場合は誰かが私を訂正してください)。についてはdata.table、間違いなくグループ単位の操作を非常に高速に実行できますが、実際に結果をワイド形式にキャストする方法がわかりません。

あなたが純粋にRでそれをやりたいのなら、私はここでスピードチャンピオンだと思います、からtapplyよりもはるかに速いです:acastreshape2

コードが正しいことをしていることを確認するために、いくつかの穴を開けて、いくつかの背の高いデータを作成します。

tall <- data.frame( dt = rep(1:100, 100),
                     tkr = rep( paste('v',1:100,sep=''), each = 100),
                     value = rnorm(1e4)) [-(1:5), ]


> system.time( replicate(100, wide <- with(tall, tapply( value, list(dt,tkr), identity))))
   user  system elapsed 
   4.73    0.00    4.73 

> system.time( replicate(100, wide <- acast( tall, tkr ~ dt)))
   user  system elapsed 
   7.93    0.03    7.98 
于 2011-03-15T13:37:50.757 に答える