计算大数据的分位数

时间:2014-02-24 10:32:33

标签: r quantile large-data

我有大约300个文件,每个文件包含1000个时间序列实现(每个文件大约76 MB)。

我想计算完整的300000个实现中每个时间步的分位数(0.05,0.50,0.95)。

我无法将1个文件中的实现合并在一起,因为它会变得太大。

最有效的方法是什么?

每个矩阵都是通过运行模型生成的,但这里有一个包含随机数的样本:

x <- matrix(rexp(10000000, rate=.1), nrow=1000)

1 个答案:

答案 0 :(得分:3)

至少有三种选择:

  1. 你确定它必须来自全套吗? 10%的样本应该是非常非常好的近似值。
  2. 300k元素不是矢量那么大,但300k x 100+列矩阵很大。将您需要的列拉入内存而不是整个矩阵(如果需要,可以在每个列上重复)。
  3. 按顺序进行,可能与较小的样本一起使用,让您开始正确的球场。对于第5个百分位数,您只需要知道当前猜测数量以及下面有多少项目。所以类似于:
    1. 取1%的样本,找到它的第5个百分位数。在上方和下方跳过一些容差,这样你就可以确定确切的第5百分位位于该范围内。
    2. 以块的形式读取矩阵。对于每个块,计算高于该范围且低于该范围的观察数。然后保留范围内的所有观察结果。
    3. 当您阅读最后一个块时,您现在有三条信息(上面的数字,下面的数字,内部的观察向量)。获取分位数的一种方法是对整个矢量进行排序并找到第n个观测值,您可以使用上述信息进行排序:对范围内的观测值进行排序,然后找到(n-count_below)th。
  4. 修改:(3)的示例。

    请注意,我不是冠军算法设计师,并且有人几乎肯定为此设计了更好的算法。而且,这种实现不是特别有效。如果速度对您很重要,请考虑Rcpp,或者甚至考虑更优化的R。制作一堆列表然后从它们中提取值并不是那么聪明,但这种方式很容易原型化,所以我选择了它。

    library(plyr)
    
    set.seed(1)
    
    # -- Configuration -- #
    desiredQuantile <- .25
    
    # -- Generate sample data -- #
    
    # Use some algorithm (sampling, iteration, or something else to come up with a range you're sure the true value lies within)
    guessedrange <- c( .2, .3 )
    # Group the observations to correspond to the OP's files
    dat <- data.frame( group = rep( seq(100), each=100 ), value = runif(10000) )
    
    # -- Apply the algorithm -- #
    
    # Count the number above/below and return the values within the range, by group
    res <- dlply( dat, .( group ), function( x, guessedrange ) {
      above <- x$value > guessedrange[2]
      below <- x$value < guessedrange[1]
      list(
        aboveCount  = sum( above ),
        belowCount = sum( below ),
        withinValues = x$value[ !above & !below ]
      )
    }, guessedrange = guessedrange )
    # Exract the count of values below and the values within the range
    belowCount <- sum( sapply( res, function(x) x$belowCount ) )
    belowCount
    withinValues <- do.call( c, sapply( res, function(x) x$withinValues ) )
    str(withinValues)
    # Count up until we find the within value we want
    desiredQuantileCount <- floor( desiredQuantile * nrow(dat) ) #! Should fix this so it averages when there's a tie
    sort(withinValues)[ desiredQuantileCount - belowCount + 1 ]
    # Compare to exact value
    quantile( dat$value, desiredQuantile )
    

    最后,该值与确切版本略有差异。我怀疑我被一个或一些同样愚蠢的解释所转移,但也许我错过了一些基本的东西。