使用apache.math3.stat.descriptive进行百分比计算不匹配

时间:2015-05-19 17:39:49

标签: java excel apache-commons-math

我正在计算以下数字列表的第95百分位数:

66,337.8,989.7,1134.6,1118.7,1097.9,1122.1,1121.3,1106.7,871,325.2,285.1,264.1,295.8,342.4

apache库使用NIST标准来计算百分位数,这与Excel使用的方法相同。根据Excel,上面列表的第95百分位应该是1125.85。

但是,使用以下代码我得到了不同的结果:

DescriptiveStatistics shortList = new DescriptiveStatistics();



@BeforeTest
@Parameters("shortStatsList")
private void buildShortStatisticsList(String list) {
    StringTokenizer tokens = new StringTokenizer(list, ",");
    while (tokens.hasMoreTokens()) {
        shortList.addValue(Double.parseDouble(tokens.nextToken()));
    }
}

@Test
@Parameters("95thPercentileShortList")
public void percentileShortListTest(String percentile) {
    Assert.assertEquals(Double.toString(shortList.getPercentile(95)), percentile);
}

此操作失败,并显示以下消息:

java.lang.AssertionError: expected:<1125.85> but was:<1134.6>
at org.testng.Assert.fail(Assert.java:89)
at org.testng.Assert.failNotEquals(Assert.java:489)

1134.6是列表中的最大值,而不是第95百分位数,所以我不知道这个值来自何处。

1 个答案:

答案 0 :(得分:2)

根据getPercentile()的文档,它使用百分位数估算算法,记录为here

  

百分位数可以从N次测量估计如下:对于第p个百分位数,将p(N + 1)设置为等于k + d表示k为整数,d为大于或等于0且小于1的分数

     
      
  1. 对于0&lt; k&lt; N,Y (p) = Y [k] + d(Y [k + 1] -Y <子> [K]

  2.   
  3. 对于k = 0,Y (p) = Y [1]

         

    请注意,任何p≤1/(N + 1)都只会设置为最小值。

  4.   
  5. 对于k≥N,Y (p) = Y [N]

         

    请注意,任何p≥N/(N + 1)都只会设置为最大值。

  6.   

基本上这意味着将请求的百分位数(0.95)乘以(N + 1)。在你的情况下,N是15,N + 1是16,所以你得到15.2。

您将其分为整个部分k(15)和d(0.2)。 k属于上述第3类。也就是说,估计百分位数最大值

如果您继续阅读我上面链接的NIST文章,您会看到标题为的部分“请注意,还有其他方法可以计算常用的百分位”。他们向您推荐Hyndman&amp; Fann,描述了几种计算百分位数的替代方法。对于存在一个 NIST方法的事情,这是一种误解。 Hyndman&amp; Fann由标签 R1 R9 表示。文章接着说:

  

某些软件包将1 + p(N-1)设置为等于k + d,然后按上述步骤操作。这是Hyndman和Fan的方法R7。这是Excel使用的方法,是R的默认方法(R分位数函数可以选择使用Hyndman&amp; Fan中讨论的九种方法中的任何一种。)

Apache的DescriptiveStatistics默认使用的方法是Hyndman&amp;粉丝的 R6 。 Excel使用的方法是 R7 。它们都是“NIST方法”,但对于少量测量,它们可以给出不同的结果。

请注意,Apache库允许您使用Percentile类来使用 R7 算法或任何其他算法。这样的事情可以解决问题:

DescriptiveStatistics shortList = new DescriptiveStatistics();
shortList.setPercentileImpl( new Percentile().
                                 withEstimationType( Percentile.EstimationType.R_7 ) );

(请注意,我没有测试过这个)。