R中的比例表更快

时间:2012-05-18 16:33:42

标签: performance r xts

我正在基于xts对象创建比例表。由于这是一个大型程序的一部分(不幸的是)需要大约10 ^ 6个循环,它会产生相当大的瓶颈,我想加快速度。

这是我开始时的一个例子:

library(quantmod)

test.xts <- xts(sample(seq(1,5, by=.5), 50, replace=T), as.Date(1:50))

system.time(for(i in 1:10000){

  prop.table(table(test.xts))

})

>user  system elapsed 
 19.86    0.00   18.58 

我已经将xts更改为矩阵,这导致了显着的速度提升。我只提到它本来是一个xts,以防我错过了一些xts的东西,这会加速它超出我已经看到的将其转换为矩阵的增益。

test.mat <- as.matrix(test.xts)

system.time(for(i in 1:10000){

  prop.table(table(test.mat))

})

>user  system elapsed 
 2.78    0.00    2.90 

但我真的希望它尽可能快,所以我希望其他人有进一步改进的建议。我希望有一个明显的方法,我忽略了。

另外一条信息是这些表的输出最终与来自不同时间段的类似输出合并,因此维度需要保持命名。 (即,我需要能够在时间1匹配'10'值的比例,在时间2匹配'10'的比例。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:5)

table()隐含地创造了一个昂贵的因素。在你的情况下,你可以使用tabulate()节省很多(超过10倍),因为你已经有了整数:

a <- tabulate(test.mat)
names(a) <- seq_along(a)
a / sum(a)
   1    2    3    4    5    6    7    8    9   10 
0.16 0.14 0.08 0.14 0.08 0.16 0.02 0.06 0.10 0.06 

定时:

system.time(for(i in 1:10000){
  a <- tabulate(test.mat)
  names(a) <- seq_along(a)
  a/sum(a)
})

 user  system elapsed 
0.208   0.002   0.210 

您的比较时机:

system.time(for(i in 1:10000) prop.table(table(test.mat)))
 user  system elapsed 
3.373   0.028   3.402 

答案 1 :(得分:3)

基于joran的评论,直接使用tabulate()可以证明更快。确实有三个值得注意的怪癖:

  1. 它只处理整数并截断小数。
  2. 它默默地忽略所有负值和零。
  3. 它为所有值1:n创建一个bin,即使计数为零
  4. 有关详细信息,请参阅?tabulate

    有了这个警告,这里的功能可以提高~9倍的速度:

    prop2 <- function(x){
      x <- tabulate(x)
      out <- x/sum(x)
      names(out) <- seq_along(out)
      return(out)
    }
    

    测试速度:

    library(rbenchmark)
    test.mat <- as.matrix(test.xts)
    f1 <- function() prop.table(table(test.mat))
    benchmark(f1(), prop2(test.mat),
               replications = 1000,
               columns = c("test", "relative", "elapsed"),
               order = "relative")
    #------
                 test relative elapsed
    2 prop2(test.mat)      1.0    0.10
    1            f1()      9.1    0.91
    

    确认输出相同:

    > prop.table(table(test.mat))
    test.mat
       1    2    3    4    5    6    7    8    9   10 
    0.04 0.02 0.20 0.12 0.08 0.10 0.06 0.14 0.12 0.12 
    > prop2(test.mat)
       1    2    3    4    5    6    7    8    9   10 
    0.04 0.02 0.20 0.12 0.08 0.10 0.06 0.14 0.12 0.12