如何估算大量未知数量的第x百分位数

时间:2017-08-30 04:42:41

标签: algorithm sampling percentile approximation

最近遇到了关于如何找到给定数字流的第x个百分位数的问题。如果流相对较小(可以存储到内存中,排序并且可以找到xth值),我基本了解如何实现这一点但我想知道如果数字流是公平的,百分位数是如何近似的大而且数字的数量是未知的。

1 个答案:

答案 0 :(得分:0)

我认为您可以使用Reservoir sampling从流k中选择统一的S元素,然后将S的xth百分位数与这些{{1}的xth百分位近似数字。 k取决于您拥有多少内存以及近似值的精确程度。

修改

以下是测试解决方案的代码示例:

k

结果是:

  

近似百分位数:29

     

真实百分位:29

对于我使用的每个// create random stream of numbers Random random = new Random(0); List<Integer> stream = new ArrayList<Integer>(); for (int i = 0; i < 100000; ++i) { stream.add((int) (random.nextGaussian() * 100 + 30)); } // get approximate percentile int k = 1000; // sample size int x = 50; // percentile // init priority queue for sampling TreeMap<Double, Integer> queue = new TreeMap<Double, Integer>(); // sample k elements from stream for (int val : stream) { queue.put(random.nextDouble(), val); if (queue.size() > k) { queue.pollFirstEntry(); } } // get xth percentile from k samples List<Integer> sample = new ArrayList<Integer>(queue.values()); Collections.sort(sample); int approxPercent = sample.get(sample.size() * x / 100); System.out.println("Approximate percentile: " + approxPercent); // get real value of the xth percentile Collections.sort(stream); int percent = stream.get(stream.size() * x / 100); System.out.println("Real percentile: " + percent); ,我得到了一个非常好的近似值,目前我不明白为什么它不适合你的情况。