2011-05-10 59 views
10

我有计算percentile(85)与一系列值(12个值)的Apache Commons,用于与阈值的评估以后作出决定的算法。结果与Excel给出的结果类似,但并不相同,有时这对于我的应用程序来说很关键,因为使用excel结果不会通过阈值,并且它与中的Apache Commons Math一样,所以我得到不同的输出。爪哇Apache的百科全书getPercentile()不同结果是MS Excel的百分

这是一个例子:互联网流量(Mbps)的每2小时

32,7076813360000000 41,2580429776000000 45,4453940200000000 48,8044409456000000 46,7462847936000000 49,8028100056000000 54,3719451144000000 41,9708134600000000 29 43719632.4亿22,4667255616000000 20,0388452248000000 28,7807757104000000

由1000 MB(电缆的容量)除以后我计算职业的百分位数(85):

Excel中:0,049153870117

阿帕奇百科全书数学:0.05003126676104001

我发现,这是可以改变的百分的实施与setPercentileImpl()(它不存在正式的一个),但我不能找到如何做到这一点的任何例子,或Excel算法(这是我被告知要实现的)。

对此的任何帮助将受到欢迎。

谢谢。

+1

你能给出一个你看到的差异的例子吗?有了数据,我们可以尝试自己? – 2011-05-10 09:49:33

+0

当然,我会用数据编辑我的问题。 – 2011-05-10 11:32:35

+1

请注意,不同结果的原因是该组值为12.对于较大的值,两种算法都会得到相似的结果。我的问题是如何在Java中实现Excel的方法。 – 2011-05-10 11:39:10

回答

5

溶液创建一个类PercentileExcel这几乎是从公共方法百分的副本,除了对如何caculate位置的微小变化:

pos=(1+p*(n-1))/100; 

然后你需要添加这行代码为了使用百分位的新类:

setPercentileImpl(PercentileExcel); 
4

从数据集计算出来的百分位数没有唯一的定义。有关最常用的定义,请参阅Wikipedia page

+0

是的,我创建了至少3个不同的。 – 2011-05-10 13:07:28

9

区别是微妙的,并由于假设。这是最容易解释的3元素的情况。假设你有三个元素(N = 3)a=x[0] < b=x[1] < c=x[2]。 Apache和Excel方法都表示元素b是第50百分位数(中位数)。然而,它们在ac上有所不同。

Apache method(和the method referenced by the NIST page)说a是25百分和c是75%百分位数,因为是分空间成N + 1块,即,四等分。

Excel的方法说a是第0百分位和c第100百分位数,当空间被划分为N-1的块,即在一半。因此,如果你想使用Excel方法,并且你不想自己编写代码,那么你可以从数组中删除最小和最大的元素,并调用Apache方法 - 它应该给你准确的除终点之外的百分位数相同的结果。

如果你想自己编码,下面给出一个简单的方法。请注意这些问题:

  • 这个阵列(因此改变它)
  • 这需要O(N日志(N))时间顺序排序,由于排序。Apache的方法使用快速选择算法,需要O(N)时间(谷歌“quickselect”如果你想知道更多)

代码(未测试,甚至编译,但应该给你一个想法)。

// warning - modifies data 
double excelPercentile(double [] data, double percentile) { array 
    Arrays.sort(data); 
    double index = percentile*(data.length-1); 
    int lower = (int)Math.floor(index); 
    if(lower<0) { // should never happen, but be defensive 
     return data[0]; 
    } 
    if(lower>=data.length-1) { // only in 100 percentile case, but be defensive 
     return data[data.length-1); 
    } 
    double fraction = index-lower; 
    // linear interpolation 
    double result=data[lower] + fraction*(data[lower+1]-data[lower]); 
    return result; 
} 
+0

谢谢。我想我创建了Commons实现的源代码 http://www.java2s.com/Open-Source/Java-Document/Science/Apache-commons-math-1.1-src/org/apache/commons/math/stat /descriptive/rank/Percentile.java.htm 我会尝试通过更改199行中的位置赋值。这应该工作,我不会改变我的代码的结构。 – 2011-05-10 13:09:53

+1

看起来它应该工作。我假设double pos = 1+ p *(n-1)/ 100; – 2011-05-10 13:27:26

+1

我假设你将创建一个新类,而不是只替换Apache jar中的Percentile类。如果Apache jar中的其他类使用此方法,这可能会很危险,也意味着您将不得不使用未来版本更新 – 2011-05-10 13:29:33

2

org.apache.commons.math3.stat.descriptive.rank.Percentile已支持rts Excel样式插值,你只需要启用它​​

public class PercentileExcel extends Percentile { 
    public PercentileExcel() throws MathIllegalArgumentException { 

    super(50.0, 
      EstimationType.R_7, // use excel style interpolation 
      NaNStrategy.REMOVED, 
      new KthSelector(new MedianOf3PivotingStrategy())); 
    } 
} 
+0

注意:这在commons-math-3.0或更低版本中不支持,只有commons-math-3.5有它。 – sichinumi 2017-03-31 21:36:44