View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.stat.inference;
23  
24  import org.hipparchus.exception.MathIllegalArgumentException;
25  import org.hipparchus.exception.NullArgumentException;
26  import org.junit.jupiter.api.Test;
27  
28  import static org.junit.jupiter.api.Assertions.assertEquals;
29  import static org.junit.jupiter.api.Assertions.assertThrows;
30  import static org.junit.jupiter.api.Assertions.assertTrue;
31  import static org.junit.jupiter.api.Assertions.fail;
32  
33  /**
34   * Test cases for the MannWhitneyUTest class.
35   */
36  
37  class MannWhitneyUTestTest {
38  
39      protected MannWhitneyUTest testStatistic = new MannWhitneyUTest();
40  
41      /**
42       * Target values for most tests below were computed using R, version 3.4.4.
43       * The wilcox.test function was used throughout, passing (along with x and y)
44       *   alternative = "two.sized"
45       *   mu = 0
46       *   paired = FALSE
47       * For the exact tests,
48       *   exact = TRUE
49       * For normal approximation (exact = false in MannWhitneyTest API)
50       *   exact = FALSE
51       *   correct = TRUE (tells R to do the continuity correction).
52       * The target for the U statistic value was obtained by running
53       * the R test twice, the second time switching the order of x and y and
54       * taking the minimum value. This is correct because the statistic that R
55       * reports as W is the Wilcoxon Rank Sum with x before y and U is the
56       * minimum of this value and the rank sum with y before x.
57       */
58  
59      @Test
60      void testMannWhitneyUSimple() {
61          /*
62           * Target values computed using R version 3.4.4.
63           */
64          final double[] x = {
65              19, 22, 16, 29, 24
66          };
67          final double[] y = {
68              20, 11, 17, 12
69          };
70  
71          assertEquals(3, testStatistic.mannWhitneyU(x, y), 1e-10);
72          assertEquals(0.11134688653,
73                              testStatistic.mannWhitneyUTest(x, y, false), 1e-5);
74          assertEquals(0.11111111111,
75                              testStatistic.mannWhitneyUTest(x, y, true), 1e-5);
76      }
77  
78      @Test
79      void testDisjoint() {
80          /*
81           * Target values computed using R version 3.4.4.
82           */
83          final double[] x = {
84              1, 2, 3, 4, 5
85          };
86          final double[] y = {
87              6, 7, 8, 9, 10, 11
88          };
89          assertEquals(0, testStatistic.mannWhitneyU(x, y), 1e-10);
90          assertEquals(0.0081131172656,
91                              testStatistic.mannWhitneyUTest(x, y, false), 1e-5);
92          assertEquals(0.004329004329,
93                              testStatistic.mannWhitneyUTest(x, y, true), 1e-5);
94  
95      }
96  
97      @Test
98      void testMannWhitneyUInputValidation() {
99          /*
100          * Samples must be present, i.e. length > 0
101          */
102         try {
103             testStatistic.mannWhitneyUTest(new double[] {}, new double[] {
104                 1.0
105             });
106             fail("x does not contain samples (exact), MathIllegalArgumentException expected");
107         } catch (MathIllegalArgumentException ex) {
108             // expected
109         }
110 
111         try {
112             testStatistic.mannWhitneyUTest(new double[] {
113                 1.0
114             }, new double[] {});
115             fail("y does not contain samples (exact), MathIllegalArgumentException expected");
116         } catch (MathIllegalArgumentException ex) {
117             // expected
118         }
119 
120         /*
121          * x and y is null
122          */
123         try {
124             testStatistic.mannWhitneyUTest(null, null);
125             fail("x and y is null (exact), NullArgumentException expected");
126         } catch (NullArgumentException ex) {
127             // expected
128         }
129 
130         try {
131             testStatistic.mannWhitneyUTest(null, null);
132             fail("x and y is null (asymptotic), NullArgumentException expected");
133         } catch (NullArgumentException ex) {
134             // expected
135         }
136 
137         /*
138          * x or y is null
139          */
140         try {
141             testStatistic.mannWhitneyUTest(null, new double[] {
142                 1.0
143             });
144             fail("x is null (exact), NullArgumentException expected");
145         } catch (NullArgumentException ex) {
146             // expected
147         }
148 
149         try {
150             testStatistic.mannWhitneyUTest(new double[] {
151                 1.0
152             }, null);
153             fail("y is null (exact), NullArgumentException expected");
154         } catch (NullArgumentException ex) {
155             // expected
156         }
157     }
158 
159     @Test
160     void testLargeDatasetExact() {
161         /**
162          * Expected values computed using R 3.4.4
163          */
164         final double[] x = {
165             11, 22, 19, 22.3, 16, 29, 24, 5.2, 7, 3, 44, 72, 43, 18, 65
166         };
167         final double[] y = {
168             15, 32, 38, 5, 6, 29.1, 31, 73, 88, 70, 50, 60, 93, 112, 190
169         };
170 
171         assertEquals(59, testStatistic.mannWhitneyU(x, y), 1e-10);
172         assertEquals(0.027925057353,
173                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
174         assertEquals(0.02635404434,
175                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
176         // Should default to exact test
177         assertEquals(0.02635404434, testStatistic.mannWhitneyUTest(x, y),
178                             1e-9);
179     }
180 
181     @Test
182     void testDatasetTooLargeForExact() {
183         /**
184          * Expected values computed using R 3.4.4
185          */
186         final double[] x = {
187             11, 22, 19, 22.3, 16, 29, 24, 5.2, 7, 3, 44, 72, 43, 18, 65, 69, 71,
188             115, 117, 119, 121, 123, 124, 125, 126, 127
189         };
190         final double[] y = {
191             15, 32, 38, 5, 6, 29.1, 31, 73, 88, 70, 50, 60, 93, 112, 190, 200,
192             201, 202, 203, 204, 205, 207, 209, 210, 212
193         };
194 
195         assertEquals(204, testStatistic.mannWhitneyU(x, y), 1e-10);
196         assertEquals(0.023177956065,
197                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
198         // Should default to normal approximation
199         assertEquals(0.023177956065,
200                             testStatistic.mannWhitneyUTest(x, y), 1e-9);
201         assertEquals(0.022259264963,
202                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
203     }
204 
205     @Test
206     void testExactHiP() {
207         /**
208          * Expected values computed using R 3.4.4
209          */
210         final double[] x = {
211             0, 2, 4, 6, 8, 10, 12, 14, 16, 18
212         };
213         final double[] y = {
214             1, 3, 5, 7, 9, 11, 13, 15, 17, 19
215         };
216         assertEquals(45, testStatistic.mannWhitneyU(x, y), 1e-10);
217         assertEquals(0.7337299957,
218                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
219         assertEquals(0.73936435082,
220                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
221 
222     }
223 
224     @Test
225     void testExactLarge() {
226         /**
227          * Expected values computed using R 3.4.4
228          */
229         final double[] x = {
230             0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34,
231             36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60
232         };
233         final double[] y = {
234             1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35,
235             37, 39, 43, 45, 49, 51, 55, 61, 63, 65, 67, 69
236         };
237         assertEquals(441, testStatistic.mannWhitneyU(x, y), 1e-10);
238         assertEquals(0.73459710599,
239                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
240         assertEquals(0.73642668965,
241                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
242     }
243 
244     @Test
245     void testExactVerySmall() {
246         /**
247          * Expected values computed using R 3.4.4
248          */
249         final double[] x = {
250             1,2
251         };
252         final double[] y = {
253             1.5, 2.5
254         };
255         assertEquals(1, testStatistic.mannWhitneyU(x, y), 1e-10);
256         assertEquals(0.66666666667,
257                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
258         assertEquals(0.6985353583,
259                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
260 
261     }
262 
263     @Test
264     void testExactDegenerate() {
265         final double[] x = {
266             1
267         };
268         final double[] y = {
269             1.5
270         };
271         assertEquals(0, testStatistic.mannWhitneyU(x, y), 1e-10);
272         assertEquals(1.0,
273                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
274         assertEquals(1.0,
275                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
276     }
277 
278     @Test
279     void testApproximateWithTies() {
280         /**
281          * Expected values computed using R 3.4.4
282          */
283         final double[] x = {
284             0, 2, 4, 6, 8, 10, 12, 14, 16, 18
285         };
286         final double[] y = {
287             1, 3, 5, 7, 8, 10, 10, 13, 15, 17, 19
288         };
289         try {
290             testStatistic.mannWhitneyUTest(x, y, true);
291         } catch (MathIllegalArgumentException ex) {
292             // expected
293         }
294         assertEquals(50.5, testStatistic.mannWhitneyU(x, y), 1e-10);
295         assertEquals(0.77784391371,
296                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
297 
298     }
299 
300     @Test
301     void testApproximateWithTies2() {
302         /**
303          * Expected values computed using R 3.4.4
304          */
305         final double[] x = {
306             2, 3, 7, 11, 23, 45, 48, 55, 70, 81, 92, 95, 97, 100, 110, 123, 125
307         };
308         final double[] y = {
309             3.5, 4, 8, 12, 25, 46, 49, 56, 70, 81, 92, 95, 97, 97, 100, 112,
310             125, 127
311         };
312         try {
313             testStatistic.mannWhitneyUTest(x, y, true);
314         } catch (MathIllegalArgumentException ex) {
315             // expected
316         }
317         assertEquals(142, testStatistic.mannWhitneyU(x, y), 1e-10);
318         assertEquals(0.72874565042,
319                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
320 
321     }
322 
323     @Test
324     void testIdenticalArrays() {
325         /**
326          * Expected values computed using R 3.4.4
327          */
328         final double[] x = {
329             1, 2, 3, 4, 5, 6, 7, 8, 9, 10
330         };
331         final double[] y = {
332             1, 2, 3, 4, 5, 6, 7, 8, 9, 10
333         };
334         try {
335             testStatistic.mannWhitneyUTest(x, y, true);
336         } catch (MathIllegalArgumentException ex) {
337             // expected
338         }
339         assertEquals(50, testStatistic.mannWhitneyU(x, y), 1e-10);
340         assertEquals(1.0, testStatistic.mannWhitneyUTest(x, y, false),
341                             1e-10);
342 
343     }
344 
345     @Test
346     void testExactThrowsOnTies() {
347         assertThrows(MathIllegalArgumentException.class, () -> {
348             final double[] x = {
349                 1, 5, 7
350             };
351             final double[] y = {
352                 2, 3, 1
353             };
354             testStatistic.mannWhitneyUTest(x, y, true);
355         });
356     }
357 
358     @Test
359     void testBigDataSet() {
360         double[] d1 = new double[1500];
361         double[] d2 = new double[1500];
362         for (int i = 0; i < 1500; i++) {
363             d1[i] = 2 * i;
364             d2[i] = 2 * i + 1;
365         }
366         double result = testStatistic.mannWhitneyUTest(d1, d2);
367         assertTrue(result > 0.1);
368     }
369 
370     @Test
371     void testBigDataSetOverflow() {
372         // MATH-1145
373         double[] d1 = new double[110000];
374         double[] d2 = new double[110000];
375         for (int i = 0; i < 110000; i++) {
376             d1[i] = i;
377             d2[i] = i;
378         }
379         assertEquals(1.0, testStatistic.mannWhitneyUTest(d1, d2, false),
380                             1E-7);
381     }
382 }