我正在计算以下数字列表的第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百分位数,所以我不知道这个值来自何处。
答案 0 :(得分:2)
根据getPercentile()
的文档,它使用百分位数估算算法,记录为here。
百分位数可以从N次测量估计如下:对于第p个百分位数,将p(N + 1)设置为等于k + d表示k为整数,d为大于或等于0且小于1的分数
对于0&lt; k&lt; N,Y (p) = Y [k] + d(Y [k + 1] 子> -Y <子> [K] 子>)
对于k = 0,Y (p) = Y [1]
请注意,任何p≤1/(N + 1)都只会设置为最小值。
- 醇>
对于k≥N,Y (p) = Y [N]
请注意,任何p≥N/(N + 1)都只会设置为最大值。
基本上这意味着将请求的百分位数(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 ) );
(请注意,我没有测试过这个)。