Java Apache Commons getPercentile()MS Excel百分位数的不同结果

时间:2011-05-10 09:43:29

标签: java excel statistics apache-commons percentile

我有一个算法,用percentile(85)计算一系列值{12}的Apache Commons,以便稍后评估一个阈值来做出决定。结果与Excel给出的结果类似,但不相等,有时这对我的应用程序至关重要,因为使用excel时,结果不会超过阈值,并且Java中的Apache Commons Math会这样做,所以我获得不同的输出。

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

  

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

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

Excel:0,049153870117

Apache Commons Math:0.05003126676104001

我发现可以用setPercentileImpl()更改百分位数的实现(它不存在官方的实现),但我找不到任何如何执行此操作的示例,或Excel算法(这是我被告知要实现的)。

欢迎任何有关此事的帮助。

谢谢。

5 个答案:

答案 0 :(得分:10)

差异是微妙的,并且由于假设。最容易用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 log(N))时间。 Apache方法使用快速选择算法,因此需要O(N)时间(谷歌“快速选择”,如果你想了解更多)

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

// 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;
 }

答案 1 :(得分:5)

解决方案是创建一个 PercentileExcel 类,这几乎是公共方法百分位数的副本,除了如何计算位置的小变化:

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

然后,您需要将此行添加到代码中,以便将新类用于百分位数:

setPercentileImpl(PercentileExcel);

答案 2 :(得分:4)

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

答案 3 :(得分:2)

org.apache.commons.math3.stat.descriptive.rank.Percentile已经支持Excel样式插值,您只需要使用EstimationType.R_7启用它

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()));
    }
}

答案 4 :(得分:1)

以下不需要新类的替代方法在3.6中有效:

DescriptiveStatistics ds = new DescriptiveStatistics();
Percentile p = new Percentile(50.0).withEstimationType(EstimationType.R_7)
                .withNaNStrategy(NaNStrategy.REMOVED)
                .withKthSelector(new KthSelector(new 
                  MedianOf3PivotingStrategy()))
ds.setPercentileImpl(p);