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.Assert;
27  import org.junit.Test;
28  
29  /**
30   * Test cases for the MannWhitneyUTest class.
31   */
32  
33  public class MannWhitneyUTestTest {
34  
35      protected MannWhitneyUTest testStatistic = new MannWhitneyUTest();
36  
37      /**
38       * Target values for most tests below were computed using R, version 3.4.4.
39       * The wilcox.test function was used throughout, passing (along with x and y)
40       *   alternative = "two.sized"
41       *   mu = 0
42       *   paired = FALSE
43       * For the exact tests,
44       *   exact = TRUE
45       * For normal approximation (exact = false in MannWhitneyTest API)
46       *   exact = FALSE
47       *   correct = TRUE (tells R to do the continuity correction).
48       * The target for the U statistic value was obtained by running
49       * the R test twice, the second time switching the order of x and y and
50       * taking the minimum value. This is correct because the statistic that R
51       * reports as W is the Wilcoxon Rank Sum with x before y and U is the
52       * minimum of this value and the rank sum with y before x.
53       */
54  
55      @Test
56      public void testMannWhitneyUSimple() {
57          /*
58           * Target values computed using R version 3.4.4.
59           */
60          final double[] x = {
61              19, 22, 16, 29, 24
62          };
63          final double[] y = {
64              20, 11, 17, 12
65          };
66  
67          Assert.assertEquals(3, testStatistic.mannWhitneyU(x, y), 1e-10);
68          Assert.assertEquals(0.11134688653,
69                              testStatistic.mannWhitneyUTest(x, y, false), 1e-5);
70          Assert.assertEquals(0.11111111111,
71                              testStatistic.mannWhitneyUTest(x, y, true), 1e-5);
72      }
73  
74      @Test
75      public void testDisjoint() {
76          /*
77           * Target values computed using R version 3.4.4.
78           */
79          final double[] x = {
80              1, 2, 3, 4, 5
81          };
82          final double[] y = {
83              6, 7, 8, 9, 10, 11
84          };
85          Assert.assertEquals(0, testStatistic.mannWhitneyU(x, y), 1e-10);
86          Assert.assertEquals(0.0081131172656,
87                              testStatistic.mannWhitneyUTest(x, y, false), 1e-5);
88          Assert.assertEquals(0.004329004329,
89                              testStatistic.mannWhitneyUTest(x, y, true), 1e-5);
90  
91      }
92  
93      @Test
94      public void testMannWhitneyUInputValidation() {
95          /*
96           * Samples must be present, i.e. length > 0
97           */
98          try {
99              testStatistic.mannWhitneyUTest(new double[] {}, new double[] {
100                 1.0
101             });
102             Assert
103                 .fail("x does not contain samples (exact), MathIllegalArgumentException expected");
104         } catch (MathIllegalArgumentException ex) {
105             // expected
106         }
107 
108         try {
109             testStatistic.mannWhitneyUTest(new double[] {
110                 1.0
111             }, new double[] {});
112             Assert
113                 .fail("y does not contain samples (exact), MathIllegalArgumentException expected");
114         } catch (MathIllegalArgumentException ex) {
115             // expected
116         }
117 
118         /*
119          * x and y is null
120          */
121         try {
122             testStatistic.mannWhitneyUTest(null, null);
123             Assert
124                 .fail("x and y is null (exact), NullArgumentException expected");
125         } catch (NullArgumentException ex) {
126             // expected
127         }
128 
129         try {
130             testStatistic.mannWhitneyUTest(null, null);
131             Assert
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             Assert.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             Assert.fail("y is null (exact), NullArgumentException expected");
154         } catch (NullArgumentException ex) {
155             // expected
156         }
157     }
158 
159     @Test
160     public 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         Assert.assertEquals(59, testStatistic.mannWhitneyU(x, y), 1e-10);
172         Assert.assertEquals(0.027925057353,
173                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
174         Assert.assertEquals(0.02635404434,
175                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
176         // Should default to exact test
177         Assert.assertEquals(0.02635404434, testStatistic.mannWhitneyUTest(x, y),
178                             1e-9);
179     }
180 
181     @Test
182     public 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         Assert.assertEquals(204, testStatistic.mannWhitneyU(x, y), 1e-10);
196         Assert.assertEquals(0.023177956065,
197                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
198         // Should default to normal approximation
199         Assert.assertEquals(0.023177956065,
200                             testStatistic.mannWhitneyUTest(x, y), 1e-9);
201         Assert.assertEquals(0.022259264963,
202                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
203     }
204 
205     @Test
206     public 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         Assert.assertEquals(45, testStatistic.mannWhitneyU(x, y), 1e-10);
217         Assert.assertEquals(0.7337299957,
218                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
219         Assert.assertEquals(0.73936435082,
220                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
221 
222     }
223 
224     @Test
225     public 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         Assert.assertEquals(441, testStatistic.mannWhitneyU(x, y), 1e-10);
238         Assert.assertEquals(0.73459710599,
239                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
240         Assert.assertEquals(0.73642668965,
241                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
242     }
243 
244     @Test
245     public 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         Assert.assertEquals(1, testStatistic.mannWhitneyU(x, y), 1e-10);
256         Assert.assertEquals(0.66666666667,
257                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
258         Assert.assertEquals(0.6985353583,
259                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
260 
261     }
262 
263     @Test
264     public void testExactDegenerate() {
265         final double[] x = {
266             1
267         };
268         final double[] y = {
269             1.5
270         };
271         Assert.assertEquals(0, testStatistic.mannWhitneyU(x, y), 1e-10);
272         Assert.assertEquals(1.0,
273                             testStatistic.mannWhitneyUTest(x, y, true), 1e-9);
274         Assert.assertEquals(1.0,
275                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
276     }
277 
278     @Test
279     public 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         Assert.assertEquals(50.5, testStatistic.mannWhitneyU(x, y), 1e-10);
295         Assert.assertEquals(0.77784391371,
296                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
297 
298     }
299 
300     @Test
301     public 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         Assert.assertEquals(142, testStatistic.mannWhitneyU(x, y), 1e-10);
318         Assert.assertEquals(0.72874565042,
319                             testStatistic.mannWhitneyUTest(x, y, false), 1e-9);
320 
321     }
322 
323     @Test
324     public 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         Assert.assertEquals(50, testStatistic.mannWhitneyU(x, y), 1e-10);
340         Assert.assertEquals(1.0, testStatistic.mannWhitneyUTest(x, y, false),
341                             1e-10);
342 
343     }
344 
345     @Test(expected = MathIllegalArgumentException.class)
346     public void testExactThrowsOnTies() {
347         final double[] x = {
348             1, 5, 7
349         };
350         final double[] y = {
351             2, 3, 1
352         };
353         testStatistic.mannWhitneyUTest(x, y, true);
354     }
355 
356     @Test
357     public void testBigDataSet() {
358         double[] d1 = new double[1500];
359         double[] d2 = new double[1500];
360         for (int i = 0; i < 1500; i++) {
361             d1[i] = 2 * i;
362             d2[i] = 2 * i + 1;
363         }
364         double result = testStatistic.mannWhitneyUTest(d1, d2);
365         Assert.assertTrue(result > 0.1);
366     }
367 
368     @Test
369     public void testBigDataSetOverflow() {
370         // MATH-1145
371         double[] d1 = new double[110000];
372         double[] d2 = new double[110000];
373         for (int i = 0; i < 110000; i++) {
374             d1[i] = i;
375             d2[i] = i;
376         }
377         Assert.assertEquals(1.0, testStatistic.mannWhitneyUTest(d1, d2, false),
378                             1E-7);
379     }
380 }