我有一种算法,该算法使用一系列值(12个值)的percentile(85)
计算Apache Commons
,以便稍后使用阈值进行评估以做出决策。结果类似于Excel给出的结果,但不相等,有时这对我的应用程序很关键,因为使用excel时结果不会超过阈值,而使用Java
中的Apache Commons Math可以达到此阈值,所以我得到了不同输出。
这里是一个示例:每2小时Internet流量(Mbps)
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算法(是告诉我要实现的目标)。
欢迎您提供任何帮助。
谢谢。
差异是细微的,是基于假设的。用3元素的情况最容易解释。假设您有三个元素(N = 3)a=x[0] < b=x[1] < c=x[2]
。 Apache和Excel方法都说元素b是第50个百分位数(中位数)。但是对于a
和c
,它们是不同的。
Apache method(和the method referenced by the NIST page表示a
是第25个百分位数,c
是75%的百分位数,因为它将空间分成N + 1个块,即四分之一。
Excel方法说a
是第0个百分点,c
是第100个百分点,因为该空间被分成N-1个块,即一半。
因此,如果您要使用Excel方法并且不想自己编写代码,则可以从数组中删除最小和最大的元素,然后调用Apache方法-它应该为您提供完全相同的结果,但超出终点的百分位数除外。
如果您想自己编写代码,下面提供了一种简单的方法。请注意以下问题:
代码(未经测试,甚至未编译,但应该可以给您带来启发)。
// 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;
}
该解决方案正在创建一个类PercentileExcel,该类几乎是commons方法中的百分位数的副本,只是对如何计算位置进行了微小的更改:
pos=(1+p*(n-1))/100;
然后您需要将此行添加到代码中,以便将新类用于百分位数:
setPercentileImpl(PercentileExcel);
没有从数据集计算得出的百分位数的唯一定义。有关使用中最常见的定义,请参见Wikipedia page。
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()));
}
}
我无法评论pbirnie的答案,但是以下不需要新类的替代方法在3.6中可行:Percentile p = new Percentile(50.0).withEstimationType(EstimationType.R_7)
.withNaNStrategy(NaNStrategy.REMOVED)
.withKthSelector(new KthSelector(new MedianOf3PivotingStrategy()))