R中最快的高宽旋转

时间:2011-03-15 03:46:06

标签: r sqlite data.table plyr reshape

我正在处理一个简单的表格

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的解决方案(或其他数据库)测试后者的性能。以前做过吗?是否有性能提升?并且,当“宽”字段(日期)的数量可变且事先不知道时,如何在sqlite中从高到宽进行转换?

2 个答案:

答案 0 :(得分:4)

我使用的方法基于tapply所做的,但速度提高了一个数量级(主要是因为没有每个单元格的函数调用)。

使用来自Prasad帖子的tall的时间:

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

答案 1 :(得分:1)

一些评论。一些SO问题解决了如何在Sql(ite)中进行从高到宽的转动:herehere。我没有太深入地看过那些,但我的印象是在SQL中这样做是很难看的,例如:你的sql查询需要在查询中明确提到所有可能的键! (如果我错了,请有人纠正我)。对于data.table,你绝对可以非常快速地进行分组操作,但我不知道如何将结果实际转换为宽格式。

如果你想纯粹用R做,我认为tapply是速度冠军,比acast的{​​{1}}快得多:

创建一些高数据,其中有一些漏洞只是为了确保代码做正确的事情:

reshape2