1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.stat.descriptive.rank;
23
24 import org.hipparchus.distribution.continuous.NormalDistribution;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.exception.NullArgumentException;
27 import org.hipparchus.random.RandomDataGenerator;
28 import org.hipparchus.stat.LocalizedStatFormats;
29 import org.hipparchus.stat.descriptive.UnivariateStatistic;
30 import org.hipparchus.stat.descriptive.UnivariateStatisticAbstractTest;
31 import org.hipparchus.stat.descriptive.rank.Percentile.EstimationType;
32 import org.hipparchus.stat.ranking.NaNStrategy;
33 import org.hipparchus.util.KthSelector;
34 import org.hipparchus.util.PivotingStrategy;
35 import org.junit.jupiter.api.Assertions;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38
39 import java.util.Arrays;
40 import java.util.Locale;
41
42 import static org.junit.jupiter.api.Assertions.assertEquals;
43 import static org.junit.jupiter.api.Assertions.assertFalse;
44 import static org.junit.jupiter.api.Assertions.assertNotEquals;
45 import static org.junit.jupiter.api.Assertions.assertThrows;
46 import static org.junit.jupiter.api.Assertions.assertTrue;
47 import static org.junit.jupiter.api.Assertions.fail;
48
49
50
51
52 public class PercentileTest extends UnivariateStatisticAbstractTest{
53
54 private double quantile;
55
56
57
58
59
60 private Percentile.EstimationType type;
61
62
63
64
65
66 private NaNStrategy nanStrategy;
67
68
69
70
71 private KthSelector kthSelector;
72
73
74
75
76 protected final double DEFAULT_PERCENTILE = 95d;
77
78
79
80
81 @BeforeEach
82 void setup() {
83 quantile = 95.0;
84 type = Percentile.EstimationType.LEGACY;
85 nanStrategy = NaNStrategy.REMOVED;
86 kthSelector = new KthSelector(PivotingStrategy.MEDIAN_OF_3);
87 }
88
89 private void reset(final double p, final Percentile.EstimationType type) {
90 this.quantile = p;
91 this.type = type;
92 nanStrategy = (type == Percentile.EstimationType.LEGACY) ? NaNStrategy.FIXED : NaNStrategy.REMOVED;
93 }
94
95 @Override
96 public Percentile getUnivariateStatistic() {
97 return new Percentile(quantile)
98 .withEstimationType(type)
99 .withNaNStrategy(nanStrategy)
100 .withKthSelector(kthSelector);
101 }
102
103 @Override
104 public double expectedValue() {
105 return this.percentile95;
106 }
107
108 @Test
109 void testHighPercentile(){
110 final double[] d = new double[]{1, 2, 3};
111 final Percentile p = new Percentile(75);
112 assertEquals(3.0, p.evaluate(d), 1.0e-5);
113 }
114
115 @Test
116 void testLowPercentile() {
117 final double[] d = new double[] {0, 1};
118 final Percentile p = new Percentile(25);
119 assertEquals(0d, p.evaluate(d), Double.MIN_VALUE);
120 }
121
122 @Test
123 void testPercentile() {
124 final double[] d = new double[] {1, 3, 2, 4};
125 final Percentile p = new Percentile(30);
126 assertEquals(1.5, p.evaluate(d), 1.0e-5);
127 p.setQuantile(25);
128 assertEquals(1.25, p.evaluate(d), 1.0e-5);
129 p.setQuantile(75);
130 assertEquals(3.75, p.evaluate(d), 1.0e-5);
131 p.setQuantile(50);
132 assertEquals(2.5, p.evaluate(d), 1.0e-5);
133
134
135 try {
136 p.evaluate(d, 0, d.length, -1.0);
137 fail();
138 } catch (final MathIllegalArgumentException ex) {
139 Assertions.assertEquals(LocalizedStatFormats.OUT_OF_BOUNDS_QUANTILE_VALUE, ex.getSpecifier());
140 Assertions.assertEquals(-1, (Double) ex.getParts()[0], 1.0e-15);
141 Assertions.assertEquals("out of bounds quantile value: -1, must be in (0, 100]",
142 ex.getMessage(Locale.TRADITIONAL_CHINESE));
143 }
144 try {
145 p.evaluate(d, 0, d.length, 101.0);
146 fail();
147 } catch (final MathIllegalArgumentException ex) {
148
149 }
150 }
151
152 @Test
153 void testNISTExample() {
154 final double[] d = new double[] {95.1772, 95.1567, 95.1937, 95.1959,
155 95.1442, 95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990, 95.1682
156 };
157 final Percentile p = new Percentile(90);
158 assertEquals(95.1981, p.evaluate(d), 1.0e-4);
159 assertEquals(95.1990, p.evaluate(d,0,d.length, 100d), 0);
160 }
161
162 @Test
163 void test5() {
164 final Percentile percentile = new Percentile(5);
165 assertEquals(this.percentile5, percentile.evaluate(testArray), getTolerance());
166 }
167
168 @Test
169 void testNullEmpty() {
170 final Percentile percentile = new Percentile(50);
171 final double[] nullArray = null;
172 final double[] emptyArray = new double[] {};
173 try {
174 percentile.evaluate(nullArray);
175 fail("Expecting NullArgumentException for null array");
176 } catch (final NullArgumentException ex) {
177
178 }
179 assertTrue(Double.isNaN(percentile.evaluate(emptyArray)));
180 }
181
182 @Test
183 void testSingleton() {
184 final Percentile percentile = new Percentile(50);
185 final double[] singletonArray = new double[] {1d};
186 assertEquals(1d, percentile.evaluate(singletonArray), 0);
187 assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
188 assertEquals(1d, percentile.evaluate(singletonArray, 0, 1, 5), 0);
189 assertEquals(1d, percentile.evaluate(singletonArray, 0, 1, 100), 0);
190 assertTrue(Double.isNaN(percentile.evaluate(singletonArray, 0, 0)));
191 }
192
193 @Test
194 void testSpecialValues() {
195 final Percentile percentile = new Percentile(50);
196 double[] specialValues = new double[] {0d, 1d, 2d, 3d, 4d, Double.NaN};
197 assertEquals(2d, percentile.evaluate(specialValues), 0);
198 specialValues = new double[] { Double.NEGATIVE_INFINITY, 1d, 2d, 3d, Double.NaN, Double.POSITIVE_INFINITY };
199 assertEquals(2d, percentile.evaluate(specialValues), 0);
200 specialValues = new double[] {1d, 1d, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY};
201 assertTrue(Double.isInfinite(percentile.evaluate(specialValues)));
202 specialValues = new double[] {1d, 1d, Double.NaN, Double.NaN};
203 assertFalse(Double.isNaN(percentile.evaluate(specialValues)));
204 assertEquals(1d, percentile.evaluate(specialValues));
205 specialValues = new double[] {1d, 1d, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY};
206
207 assertTrue(Double.isNaN(percentile.evaluate(specialValues)));
208 }
209
210 @Test
211 void testSetQuantile() {
212 final Percentile percentile = new Percentile(10);
213 percentile.setQuantile(100);
214 assertEquals(100, percentile.getQuantile(), 0);
215 try {
216 percentile.setQuantile(0);
217 fail("Expecting MathIllegalArgumentException");
218 } catch (final MathIllegalArgumentException ex) {
219
220 }
221 try {
222 new Percentile(0);
223 fail("Expecting MathIllegalArgumentException");
224 } catch (final MathIllegalArgumentException ex) {
225
226 }
227 }
228
229
230
231
232
233
234 @Test
235 void testAllTechniquesHighPercentile() {
236 final double[] d = new double[] { 1, 2, 3 };
237 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 3d }, { Percentile.EstimationType.R_1, 3d },
238 { Percentile.EstimationType.R_2, 3d }, { Percentile.EstimationType.R_3, 2d }, { Percentile.EstimationType.R_4, 2.25 }, { Percentile.EstimationType.R_5, 2.75 },
239 { Percentile.EstimationType.R_6, 3d }, { Percentile.EstimationType.R_7, 2.5 },{ Percentile.EstimationType.R_8, 2.83333 }, {Percentile.EstimationType.R_9,2.81250} },
240 75d, 1.0e-5);
241 }
242
243 @Test
244 void testAllTechniquesLowPercentile() {
245 final double[] d = new double[] { 0, 1 };
246 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 0d }, { Percentile.EstimationType.R_1, 0d },
247 { Percentile.EstimationType.R_2, 0d }, { Percentile.EstimationType.R_3, 0d }, { Percentile.EstimationType.R_4, 0d }, {Percentile.EstimationType.R_5, 0d}, {Percentile.EstimationType.R_6, 0d},
248 { Percentile.EstimationType.R_7, 0.25 }, { Percentile.EstimationType.R_8, 0d }, {Percentile.EstimationType.R_9, 0d} },
249 25d, Double.MIN_VALUE);
250 }
251
252 public void checkAllTechniquesPercentile() {
253 final double[] d = new double[] { 1, 3, 2, 4 };
254
255 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 1.5d },
256 { Percentile.EstimationType.R_1, 2d }, { Percentile.EstimationType.R_2, 2d }, { Percentile.EstimationType.R_3, 1d }, { Percentile.EstimationType.R_4, 1.2 }, {Percentile.EstimationType.R_5, 1.7},
257 { Percentile.EstimationType.R_6, 1.5 },{ Percentile.EstimationType.R_7, 1.9 }, { Percentile.EstimationType.R_8, 1.63333 },{ Percentile.EstimationType.R_9, 1.65 } },
258 30d, 1.0e-05);
259
260 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 1.25d },
261 { Percentile.EstimationType.R_1, 1d }, { Percentile.EstimationType.R_2, 1.5d }, { Percentile.EstimationType.R_3, 1d }, { Percentile.EstimationType.R_4, 1d }, {Percentile.EstimationType.R_5, 1.5},
262 { Percentile.EstimationType.R_6, 1.25 },{ Percentile.EstimationType.R_7, 1.75 },
263 { Percentile.EstimationType.R_8, 1.41667 }, { Percentile.EstimationType.R_9, 1.43750 } }, 25d, 1.0e-05);
264
265 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 3.75d },
266 { Percentile.EstimationType.R_1, 3d }, { Percentile.EstimationType.R_2, 3.5d }, { Percentile.EstimationType.R_3, 3d }, { Percentile.EstimationType.R_4, 3d },
267 { Percentile.EstimationType.R_5, 3.5d },{ Percentile.EstimationType.R_6, 3.75d }, { Percentile.EstimationType.R_7, 3.25 },
268 { Percentile.EstimationType.R_8, 3.58333 },{ Percentile.EstimationType.R_9, 3.56250} }, 75d, 1.0e-05);
269
270 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 2.5d },
271 { Percentile.EstimationType.R_1, 2d }, { Percentile.EstimationType.R_2, 2.5d }, { Percentile.EstimationType.R_3, 2d }, { Percentile.EstimationType.R_4, 2d },
272 { Percentile.EstimationType.R_5, 2.5 },{ Percentile.EstimationType.R_6, 2.5 },{ Percentile.EstimationType.R_7, 2.5 },
273 { Percentile.EstimationType.R_8, 2.5 },{ Percentile.EstimationType.R_9, 2.5 } }, 50d, 1.0e-05);
274
275
276 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
277 try {
278 reset(-1.0, e);
279 getUnivariateStatistic().evaluate(d, 0, d.length);
280 fail();
281 } catch (final MathIllegalArgumentException ex) {
282
283 }
284 }
285
286 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
287 try {
288 reset(101.0, e);
289 getUnivariateStatistic().evaluate(d, 0, d.length);
290 fail();
291 } catch (final MathIllegalArgumentException ex) {
292
293 }
294 }
295 }
296
297 @Test
298 void testAllTechniquesPercentileUsingMedianOf3Pivoting() {
299 kthSelector = new KthSelector(PivotingStrategy.MEDIAN_OF_3);
300 checkAllTechniquesPercentile();
301 }
302
303 @Test
304 void testAllTechniquesPercentileUsingCentralPivoting() {
305 kthSelector = new KthSelector(PivotingStrategy.CENTRAL);
306 checkAllTechniquesPercentile();
307 }
308
309 @Test
310 void testAllTechniquesNISTExample() {
311 final double[] d =
312 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.0610,
313 95.1591, 95.1195, 95.1772, 95.0925, 95.1990, 95.1682 };
314
315 testAssertMappedValues(d, new Object[][] { { Percentile.EstimationType.LEGACY, 95.1981 },
316 { Percentile.EstimationType.R_1, 95.19590 }, { Percentile.EstimationType.R_2, 95.19590 }, { Percentile.EstimationType.R_3, 95.19590 },
317 { Percentile.EstimationType.R_4, 95.19546 }, { Percentile.EstimationType.R_5, 95.19683 }, { Percentile.EstimationType.R_6, 95.19807 },
318 { Percentile.EstimationType.R_7, 95.19568 }, { Percentile.EstimationType.R_8, 95.19724 }, { Percentile.EstimationType.R_9, 95.19714 } }, 90d,
319 1.0e-04);
320
321 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
322 reset(100.0, e);
323 assertEquals(95.1990, getUnivariateStatistic().evaluate(d), 1.0e-4);
324 }
325 }
326
327 @Test
328 void testAllTechniques5() {
329 reset(5, Percentile.EstimationType.LEGACY);
330 final UnivariateStatistic percentile = getUnivariateStatistic();
331 assertEquals(this.percentile5, percentile.evaluate(testArray), getTolerance());
332 testAssertMappedValues(testArray,
333 new Object[][] { { Percentile.EstimationType.LEGACY, percentile5 }, { Percentile.EstimationType.R_1, 8.8000 },
334 { Percentile.EstimationType.R_2, 8.8000 }, { Percentile.EstimationType.R_3, 8.2000 }, { Percentile.EstimationType.R_4, 8.2600 },
335 { Percentile.EstimationType.R_5, 8.5600 }, { Percentile.EstimationType.R_6, 8.2900 },
336 { Percentile.EstimationType.R_7, 8.8100 }, { Percentile.EstimationType.R_8, 8.4700 },
337 { Percentile.EstimationType.R_9, 8.4925 }}, 5d, getTolerance());
338 }
339
340 @Test
341 void testAllTechniquesNullEmpty() {
342
343 final double[] nullArray = null;
344 final double[] emptyArray = new double[] {};
345 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
346 reset (50, e);
347 final UnivariateStatistic percentile = getUnivariateStatistic();
348 try {
349 percentile.evaluate(nullArray);
350 fail("Expecting NullArgumentException "
351 + "for null array");
352 } catch (final NullArgumentException ex) {
353
354 }
355 assertTrue(Double.isNaN(percentile.evaluate(emptyArray)));
356 }
357
358 }
359
360 @Test
361 void testAllTechniquesSingleton() {
362 final double[] singletonArray = new double[] { 1d };
363 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
364 reset (50, e);
365 final UnivariateStatistic percentile = getUnivariateStatistic();
366 assertEquals(1d, percentile.evaluate(singletonArray), 0);
367 assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
368 assertEquals(1d, new Percentile().evaluate(singletonArray, 0, 1, 5), 0);
369 assertEquals(1d, new Percentile().evaluate(singletonArray, 0, 1, 100), 0);
370 assertTrue(Double.isNaN(percentile.evaluate(singletonArray, 0, 0)));
371 }
372 }
373
374 @Test
375 void testAllTechniquesEmpty() {
376 final double[] singletonArray = new double[] { };
377 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
378 reset (50, e);
379 final UnivariateStatistic percentile = getUnivariateStatistic();
380 assertEquals(Double.NaN, percentile.evaluate(singletonArray), 0);
381 assertEquals(Double.NaN, percentile.evaluate(singletonArray, 0, 0), 0);
382 assertEquals(Double.NaN, new Percentile().evaluate(singletonArray, 0, 0, 5), 0);
383 assertEquals(Double.NaN, new Percentile().evaluate(singletonArray, 0, 0, 100), 0);
384 assertTrue(Double.isNaN(percentile.evaluate(singletonArray, 0, 0)));
385 }
386 }
387
388 @Test
389 void testReplaceNanInRange() {
390 final double[] specialValues =
391 new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN, Double.NaN, 5d, 7d, Double.NaN, 8d};
392 assertEquals(3.5, new Percentile(50d).evaluate(specialValues), 0d);
393 reset (50, Percentile.EstimationType.R_1);
394 assertEquals(3d, getUnivariateStatistic().evaluate(specialValues), 0d);
395 reset (50, Percentile.EstimationType.R_2);
396 assertEquals(3.5d, getUnivariateStatistic().evaluate(specialValues), 0d);
397 assertEquals(Double.POSITIVE_INFINITY,
398 new Percentile(70).withNaNStrategy(NaNStrategy.MAXIMAL).evaluate(specialValues),
399 0d);
400 }
401
402 @Test
403 void testRemoveNan() {
404 final double[] specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
405 final double[] expectedValues = new double[] { 0d, 1d, 2d, 3d, 4d };
406 reset (50, Percentile.EstimationType.R_1);
407 assertEquals(2.0, getUnivariateStatistic().evaluate(specialValues), 0d);
408 assertEquals(2.0, getUnivariateStatistic().evaluate(expectedValues),0d);
409 assertTrue(Double.isNaN(getUnivariateStatistic().evaluate(specialValues,5,1)));
410 assertEquals(4d, getUnivariateStatistic().evaluate(specialValues, 4, 2), 0d);
411 assertEquals(3d, getUnivariateStatistic().evaluate(specialValues,3,3),0d);
412 reset(50, Percentile.EstimationType.R_2);
413 assertEquals(3.5d, getUnivariateStatistic().evaluate(specialValues,3,3),0d);
414 }
415
416 @Test
417 void testPercentileCopy() {
418 reset(50d, Percentile.EstimationType.LEGACY);
419 final Percentile original = getUnivariateStatistic();
420 final Percentile copy = new Percentile(original);
421 assertEquals(original.getNaNStrategy(),copy.getNaNStrategy());
422 assertEquals(original.getQuantile(), copy.getQuantile(),0d);
423 assertEquals(original.getEstimationType(),copy.getEstimationType());
424 assertEquals(NaNStrategy.FIXED, original.getNaNStrategy());
425 }
426
427 @Test
428 void testAllTechniquesSpecialValues() {
429 reset(50d, Percentile.EstimationType.LEGACY);
430 final UnivariateStatistic percentile = getUnivariateStatistic();
431 double[] specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
432 assertEquals(2.5d, percentile.evaluate(specialValues), 0);
433
434 testAssertMappedValues(specialValues, new Object[][] {
435 { Percentile.EstimationType.LEGACY, 2.5d }, { Percentile.EstimationType.R_1, 2.0 }, { Percentile.EstimationType.R_2, 2.0 }, { Percentile.EstimationType.R_3, 1.0 },
436 { Percentile.EstimationType.R_4, 1.5 }, { Percentile.EstimationType.R_5, 2.0 }, { Percentile.EstimationType.R_6, 2.0 },
437 { Percentile.EstimationType.R_7, 2.0 }, { Percentile.EstimationType.R_8, 2.0 }, { Percentile.EstimationType.R_9, 2.0 }}, 50d, 0d);
438
439 specialValues =
440 new double[] { Double.NEGATIVE_INFINITY, 1d, 2d, 3d, Double.NaN, Double.POSITIVE_INFINITY };
441 assertEquals(2.5d, percentile.evaluate(specialValues), 0);
442
443 testAssertMappedValues(specialValues, new Object[][] {
444 { Percentile.EstimationType.LEGACY, 2.5d }, { Percentile.EstimationType.R_1, 2.0 }, { Percentile.EstimationType.R_2, 2.0 }, { Percentile.EstimationType.R_3, 1.0 },
445 { Percentile.EstimationType.R_4, 1.5 }, { Percentile.EstimationType.R_5, 2.0 }, { Percentile.EstimationType.R_7, 2.0 }, { Percentile.EstimationType.R_7, 2.0 },
446 { Percentile.EstimationType.R_8, 2.0 }, { Percentile.EstimationType.R_9, 2.0 } }, 50d, 0d);
447
448 specialValues =
449 new double[] { 1d, 1d, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY };
450 assertTrue(Double.isInfinite(percentile.evaluate(specialValues)));
451
452 testAssertMappedValues(specialValues, new Object[][] {
453
454 { Percentile.EstimationType.LEGACY, Double.POSITIVE_INFINITY },
455 { Percentile.EstimationType.R_1,Double.NaN },
456 { Percentile.EstimationType.R_2, Double.NaN },
457 { Percentile.EstimationType.R_3, Double.NaN }, { Percentile.EstimationType.R_4, Double.NaN },
458 { Percentile.EstimationType.R_5, Double.POSITIVE_INFINITY },
459 { Percentile.EstimationType.R_6, Double.POSITIVE_INFINITY },
460 { Percentile.EstimationType.R_7, Double.POSITIVE_INFINITY },
461 { Percentile.EstimationType.R_8, Double.POSITIVE_INFINITY },
462 { Percentile.EstimationType.R_9, Double.POSITIVE_INFINITY }, }, 50d, 0d);
463
464 specialValues = new double[] { 1d, 1d, Double.NaN, Double.NaN };
465 assertTrue(Double.isNaN(percentile.evaluate(specialValues)));
466 testAssertMappedValues(specialValues, new Object[][] {
467 { Percentile.EstimationType.LEGACY, Double.NaN }, { Percentile.EstimationType.R_1, 1.0 }, { Percentile.EstimationType.R_2, 1.0 }, { Percentile.EstimationType.R_3, 1.0 },
468 { Percentile.EstimationType.R_4, 1.0 }, { Percentile.EstimationType.R_5, 1.0 },{ Percentile.EstimationType.R_6, 1.0 },{ Percentile.EstimationType.R_7, 1.0 },
469 { Percentile.EstimationType.R_8, 1.0 }, { Percentile.EstimationType.R_9, 1.0 },}, 50d, 0d);
470
471 specialValues =
472 new double[] { 1d, 1d, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY };
473
474 testAssertMappedValues(specialValues, new Object[][] {
475 { Percentile.EstimationType.LEGACY, Double.NaN }, { Percentile.EstimationType.R_1, Double.NaN },
476 { Percentile.EstimationType.R_2, Double.NaN }, { Percentile.EstimationType.R_3, Double.NaN }, { Percentile.EstimationType.R_4, Double.NaN },
477 { Percentile.EstimationType.R_5, Double.NaN }, { Percentile.EstimationType.R_6, Double.NaN },
478 { Percentile.EstimationType.R_7, Double.NaN }, { Percentile.EstimationType.R_8, Double.NaN }, { Percentile.EstimationType.R_9, Double.NaN }
479 }, 50d, 0d);
480 }
481
482 @Test
483 void testAllTechniquesSetQuantile() {
484 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
485 reset(10, e);
486 final Percentile percentile = getUnivariateStatistic();
487 percentile.setQuantile(100);
488 assertEquals(100, percentile.getQuantile(), 0);
489 try {
490 percentile.setQuantile(0);
491 fail("Expecting MathIllegalArgumentException");
492 } catch (final MathIllegalArgumentException ex) {
493
494 }
495 try {
496 new Percentile(0);
497 fail("Expecting MathIllegalArgumentException");
498 } catch (final MathIllegalArgumentException ex) {
499
500 }
501 }
502 }
503
504 @Test
505 void testAllTechniquesEvaluateArraySegmentWeighted() {
506 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
507 reset(quantile, e);
508 testEvaluateArraySegmentWeighted();
509 }
510 }
511
512 @Test
513 void testAllTechniquesEvaluateArraySegment() {
514 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
515 reset(quantile, e);
516 testEvaluateArraySegment();
517 }
518 }
519
520 @Test
521 void testAllTechniquesWeightedConsistency() {
522 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
523 reset(quantile, e);
524 testWeightedConsistency();
525 }
526 }
527
528 @Test
529 void testAllTechniquesEvaluation() {
530
531 testAssertMappedValues(testArray, new Object[][] { { Percentile.EstimationType.LEGACY, 20.820 },
532 { Percentile.EstimationType.R_1, 19.800 }, { Percentile.EstimationType.R_2, 19.800 }, { Percentile.EstimationType.R_3, 19.800 },
533 { Percentile.EstimationType.R_4, 19.310 }, { Percentile.EstimationType.R_5, 20.280 }, { Percentile.EstimationType.R_6, 20.820 },
534 { Percentile.EstimationType.R_7, 19.555 }, { Percentile.EstimationType.R_8, 20.460 },{ Percentile.EstimationType.R_9, 20.415} },
535 DEFAULT_PERCENTILE, tolerance);
536 }
537
538 @Test
539 void testPercentileWithTechnique() {
540 reset (50, Percentile.EstimationType.LEGACY);
541 final Percentile p = getUnivariateStatistic();
542 assertEquals(Percentile.EstimationType.LEGACY, p.getEstimationType());
543 assertNotEquals(Percentile.EstimationType.R_1, p.getEstimationType());
544 }
545
546 static final int TINY = 10, SMALL = 50, NOMINAL = 100, MEDIUM = 500,
547 STANDARD = 1000, BIG = 10000, VERY_BIG = 50000, LARGE = 1000000,
548 VERY_LARGE = 10000000;
549 static final int[] sampleSizes= { TINY, SMALL, NOMINAL, MEDIUM, STANDARD, BIG };
550
551 @Test
552 void testStoredVsDirect() {
553 final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(100);
554 final NormalDistribution normalDistribution = new NormalDistribution(4000, 50);
555 for (final int sampleSize:sampleSizes) {
556 final double[] data = randomDataGenerator.nextDeviates(normalDistribution, sampleSize);
557 for (final double p:new double[] {50d,95d}) {
558 for (final Percentile.EstimationType e : Percentile.EstimationType.values()) {
559 reset(p, e);
560 final Percentile pStoredData = getUnivariateStatistic();
561 pStoredData.setData(data);
562 final double storedDataResult=pStoredData.evaluate();
563 pStoredData.setData(null);
564 final Percentile pDirect = getUnivariateStatistic();
565 assertEquals(storedDataResult,
566 pDirect.evaluate(data), 0d, "Sample="+sampleSize+",P="+p+" e="+e);
567 }
568 }
569 }
570 }
571
572 @Test
573 void testPercentileWithDataRef() {
574 reset(50.0, Percentile.EstimationType.R_7);
575 final Percentile p = getUnivariateStatistic();
576 p.setData(testArray);
577 assertEquals(Percentile.EstimationType.R_7, p.getEstimationType());
578 assertNotEquals(Percentile.EstimationType.R_1, p.getEstimationType());
579 assertEquals(12d, p.evaluate(), 0d);
580 assertEquals(12.16d, p.evaluate(60d), 0d);
581 }
582
583 @Test
584 void testNullEstimation() {
585 assertThrows(NullArgumentException.class, () -> {
586 type = null;
587 getUnivariateStatistic();
588 });
589 }
590
591 @Test
592 void testAllEstimationTechniquesOnlyLimits() {
593 final int N=testArray.length;
594
595 final double[] input = testArray.clone();
596 Arrays.sort(input);
597 final double min = input[0];
598 final double max=input[input.length-1];
599
600 final Object[][] map =
601 new Object[][] { { Percentile.EstimationType.LEGACY, 0d, 1d }, { Percentile.EstimationType.R_1, 0d, 1d },
602 { Percentile.EstimationType.R_2, 0d,1d }, { Percentile.EstimationType.R_3, 0.5/N,1d },
603 { Percentile.EstimationType.R_4, 1d/N-0.001,1d },
604 { Percentile.EstimationType.R_5, 0.5/N-0.001,(N-0.5)/N}, { Percentile.EstimationType.R_6, 0.99d/(N+1),
605 1.01d*N/(N+1)},
606 { Percentile.EstimationType.R_7, 0d,1d}, { Percentile.EstimationType.R_8, 1.99d/3/(N+1d/3),
607 (N-1d/3)/(N+1d/3)},
608 { Percentile.EstimationType.R_9, 4.99d/8/(N+0.25), (N-3d/8)/(N+0.25)} };
609
610 for(final Object[] arr:map) {
611 final Percentile.EstimationType t= (Percentile.EstimationType) arr[0];
612 double pMin=(Double)arr[1];
613 final double pMax=(Double)arr[2];
614 assertEquals(0d, t.index(pMin, N),0d,"Type:"+t);
615 assertEquals(N, t.index(pMax, N),0.5d,"Type:"+t);
616 pMin=pMin==0d?pMin+0.01:pMin;
617 testAssertMappedValues(testArray, new Object[][] { { t, min }}, pMin, 0.01);
618 testAssertMappedValues(testArray, new Object[][] { { t, max }}, pMax * 100, tolerance);
619 }
620 }
621
622 @Test
623 void testAllEstimationTechniquesOnly() {
624 assertEquals("Legacy Hipparchus",Percentile.EstimationType.LEGACY.getName());
625 final Object[][] map =
626 new Object[][] { { Percentile.EstimationType.LEGACY, 20.82 }, { Percentile.EstimationType.R_1, 19.8 },
627 { Percentile.EstimationType.R_2, 19.8 }, { Percentile.EstimationType.R_3, 19.8 }, { Percentile.EstimationType.R_4, 19.310 },
628 { Percentile.EstimationType.R_5, 20.280}, { Percentile.EstimationType.R_6, 20.820},
629 { Percentile.EstimationType.R_7, 19.555 }, { Percentile.EstimationType.R_8, 20.460 },{Percentile.EstimationType.R_9,20.415} };
630 try {
631 Percentile.EstimationType.LEGACY.evaluate(testArray, -1d, new KthSelector(PivotingStrategy.MEDIAN_OF_3));
632 } catch (final MathIllegalArgumentException oore) {
633 }
634 try {
635 Percentile.EstimationType.LEGACY.evaluate(testArray, 101d, new KthSelector());
636 } catch (final MathIllegalArgumentException oore) {
637 }
638 try {
639 Percentile.EstimationType.LEGACY.evaluate(testArray, 50d, new KthSelector());
640 } catch(final MathIllegalArgumentException oore) {
641 }
642 for (final Object[] o : map) {
643 final Percentile.EstimationType e = (Percentile.EstimationType) o[0];
644 final double expected = (Double) o[1];
645 final double result = e.evaluate(testArray, DEFAULT_PERCENTILE, new KthSelector());
646 assertEquals(expected, result, tolerance, "expected[" + e + "] = " + expected +
647 " but was = " + result);
648 }
649 }
650
651 @Test
652 void testAllEstimationTechniquesOnlyForAllPivotingStrategies() {
653
654 assertEquals("Legacy Hipparchus",Percentile.EstimationType.LEGACY.getName());
655
656 for (final PivotingStrategy strategy : PivotingStrategy.values()) {
657 kthSelector = new KthSelector(strategy);
658 testAllEstimationTechniquesOnly();
659 }
660 }
661
662 @Test
663 void testAllEstimationTechniquesOnlyForExtremeIndexes() {
664 final double MAX=100;
665 final Object[][] map =
666 new Object[][] { { Percentile.EstimationType.LEGACY, 0d, MAX}, { Percentile.EstimationType.R_1, 0d,MAX+0.5 },
667 { Percentile.EstimationType.R_2, 0d,MAX}, { Percentile.EstimationType.R_3, 0d,MAX }, { Percentile.EstimationType.R_4, 0d,MAX },
668 { Percentile.EstimationType.R_5, 0d,MAX }, { Percentile.EstimationType.R_6, 0d,MAX },
669 { Percentile.EstimationType.R_7, 0d,MAX }, { Percentile.EstimationType.R_8, 0d,MAX }, { Percentile.EstimationType.R_9, 0d,MAX } };
670 for (final Object[] o : map) {
671 final Percentile.EstimationType e = (Percentile.EstimationType) o[0];
672 assertEquals(((Double)o[1]).doubleValue(), e.index(0d, (int)MAX),0d);
673 assertEquals(((Double)o[2]).doubleValue(), e.index(1.0, (int)MAX),0d,"Enum:"+e);
674 }
675 }
676
677 @Test
678 void testAllEstimationTechniquesOnlyForNullsAndOOR() {
679
680 final Object[][] map =
681 new Object[][] { { Percentile.EstimationType.LEGACY, 20.82 }, { Percentile.EstimationType.R_1, 19.8 },
682 { Percentile.EstimationType.R_2, 19.8 }, { Percentile.EstimationType.R_3, 19.8 }, { Percentile.EstimationType.R_4, 19.310 },
683 { Percentile.EstimationType.R_5, 20.280}, { Percentile.EstimationType.R_6, 20.820},
684 { Percentile.EstimationType.R_7, 19.555 }, { Percentile.EstimationType.R_8, 20.460 },{ Percentile.EstimationType.R_9, 20.415 } };
685 for (final Object[] o : map) {
686 final Percentile.EstimationType e = (Percentile.EstimationType) o[0];
687 try {
688 e.evaluate(null, DEFAULT_PERCENTILE, new KthSelector());
689 fail("Expecting NullArgumentException");
690 } catch (final NullArgumentException nae) {
691
692 }
693 try {
694 e.evaluate(testArray, 120, new KthSelector());
695 fail("Expecting MathIllegalArgumentException");
696 } catch (final MathIllegalArgumentException oore) {
697
698 }
699 }
700 }
701
702
703
704
705
706
707
708
709
710
711 protected void testAssertMappedValues(final double[] data, final Object[][] map,
712 final Double p, final Double tolerance) {
713 for (final Object[] o : map) {
714 final Percentile.EstimationType e = (Percentile.EstimationType) o[0];
715 final double expected = (Double) o[1];
716 try {
717 reset(p, e);
718 final double result = getUnivariateStatistic().evaluate(data);
719 assertEquals(expected, result, tolerance, "expected[" + e + "] = " + expected +
720 " but was = " + result);
721 } catch(final Exception ex) {
722 fail("Exception occured for estimation type "+e+":"+
723 ex.getLocalizedMessage());
724 }
725 }
726 }
727
728
729 @Test
730 void testNanStrategySpecific() {
731 double[] specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
732 assertTrue(Double.isNaN(new Percentile(50d).withEstimationType(Percentile.EstimationType.LEGACY).withNaNStrategy(NaNStrategy.MAXIMAL).evaluate(specialValues, 3, 3)));
733 assertEquals(2d,new Percentile(50d).withEstimationType(Percentile.EstimationType.R_1).withNaNStrategy(NaNStrategy.REMOVED).evaluate(specialValues),0d);
734 assertEquals(Double.NaN,new Percentile(50d).withEstimationType(Percentile.EstimationType.R_5).withNaNStrategy(NaNStrategy.REMOVED).evaluate(new double[] {Double.NaN,Double.NaN,Double.NaN}),0d);
735 assertEquals(50d,new Percentile(50d).withEstimationType(Percentile.EstimationType.R_7).withNaNStrategy(NaNStrategy.MINIMAL).evaluate(new double[] {50d,50d,50d},1,2),0d);
736
737 specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN, Double.NaN };
738 assertEquals(3.5,new Percentile().evaluate(specialValues, 3, 4),0d);
739 assertEquals(4d,new Percentile().evaluate(specialValues, 4, 3),0d);
740 assertTrue(Double.isNaN(new Percentile().evaluate(specialValues, 5, 2)));
741
742 specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN, Double.NaN, 5d, 6d };
743 assertEquals(4.5,new Percentile().evaluate(specialValues, 3, 6),0d);
744 assertEquals(5d,new Percentile().evaluate(specialValues, 4, 5),0d);
745 assertTrue(Double.isNaN(new Percentile().evaluate(specialValues, 5, 2)));
746 assertTrue(Double.isNaN(new Percentile().evaluate(specialValues, 5, 1)));
747 assertEquals(5.5,new Percentile().evaluate(specialValues, 5, 4),0d);
748 }
749
750
751 @Test
752 void testNanStrategyFailed() {
753 assertThrows(MathIllegalArgumentException.class, () -> {
754 double[] specialValues =
755 new double[]{0d, 1d, 2d, 3d, 4d, Double.NaN};
756 new Percentile(50d).
757 withEstimationType(Percentile.EstimationType.R_9).
758 withNaNStrategy(NaNStrategy.FAILED).
759 evaluate(specialValues);
760 });
761 }
762
763 @Test
764 void testAllTechniquesSpecialValuesWithNaNStrategy() {
765 double[] specialValues =
766 new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
767 try {
768 new Percentile(50d).withEstimationType(Percentile.EstimationType.LEGACY).withNaNStrategy(null);
769 fail("Expecting NullArgumentArgumentException "
770 + "for null Nan Strategy");
771 } catch (NullArgumentException ex) {
772
773 }
774
775 testAssertMappedValues(specialValues, new Object[][] {
776 { Percentile.EstimationType.LEGACY, 2.5d }, { Percentile.EstimationType.R_1, 2.0 }, { Percentile.EstimationType.R_2, 2.0 }, { Percentile.EstimationType.R_3, 1.0 },
777 { Percentile.EstimationType.R_4, 1.5 }, { Percentile.EstimationType.R_5, 2.0 }, { Percentile.EstimationType.R_6, 2.0 },
778 { Percentile.EstimationType.R_7, 2.0 }, { Percentile.EstimationType.R_8, 2.0 }, { Percentile.EstimationType.R_9, 2.0 }}, 50d, 0d);
779
780
781 testAssertMappedValues(specialValues, new Object[][] {
782 { Percentile.EstimationType.LEGACY, 2.5d }, { Percentile.EstimationType.R_1, 2.0 }, { Percentile.EstimationType.R_2, 2.5 }, { Percentile.EstimationType.R_3, 2.0 },
783 { Percentile.EstimationType.R_4, 2.0 }, { Percentile.EstimationType.R_5, 2.5 }, { Percentile.EstimationType.R_6, 2.5 },
784 { Percentile.EstimationType.R_7, 2.5 }, { Percentile.EstimationType.R_8, 2.5 }, { Percentile.EstimationType.R_9, 2.5 }}, 50d, 0d,
785 NaNStrategy.MAXIMAL);
786
787
788 testAssertMappedValues(specialValues, new Object[][] {
789 { Percentile.EstimationType.LEGACY, 1.5d }, { Percentile.EstimationType.R_1, 1.0 }, { Percentile.EstimationType.R_2, 1.5 }, { Percentile.EstimationType.R_3, 1.0 },
790 { Percentile.EstimationType.R_4, 1.0 }, { Percentile.EstimationType.R_5, 1.5 }, { Percentile.EstimationType.R_6, 1.5 },
791 { Percentile.EstimationType.R_7, 1.5 }, { Percentile.EstimationType.R_8, 1.5 }, { Percentile.EstimationType.R_9, 1.5 }}, 50d, 0d,
792 NaNStrategy.MINIMAL);
793
794
795
796 testAssertMappedValues(specialValues, new Object[][] {
797 { Percentile.EstimationType.LEGACY, 2.0 }, { Percentile.EstimationType.R_1, 2.0 }, { Percentile.EstimationType.R_2, 2.0 }, { Percentile.EstimationType.R_3, 1.0 },
798 { Percentile.EstimationType.R_4, 1.5 }, { Percentile.EstimationType.R_5, 2.0 }, { Percentile.EstimationType.R_6, 2.0 },
799 { Percentile.EstimationType.R_7, 2.0 }, { Percentile.EstimationType.R_8, 2.0 }, { Percentile.EstimationType.R_9, 2.0 }}, 50d, 0d,
800 NaNStrategy.REMOVED);
801 }
802
803
804
805
806
807
808
809
810
811
812 protected void testAssertMappedValues(double[] data, Object[][] map,
813 Double p, Double tolerance, NaNStrategy nanStrategy) {
814 for (Object[] o : map) {
815 Percentile.EstimationType e = (Percentile.EstimationType) o[0];
816 double expected = (Double) o[1];
817 try {
818 double result = new Percentile(p).withEstimationType(e).withNaNStrategy(nanStrategy).evaluate(data);
819 assertEquals(expected, result, tolerance, "expected[" + e + "] = " + expected + " but was = " + result);
820 } catch(Exception ex) {
821 fail("Exception occured for estimation type " + e + ":" + ex.getLocalizedMessage());
822 }
823 }
824 }
825
826 }