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    *      http://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  package org.apache.commons.math.stat.inference;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import junit.framework.Test;
23  import junit.framework.TestCase;
24  import junit.framework.TestSuite;
25  import org.apache.commons.math.stat.descriptive.SummaryStatistics;
26  /**
27   * Test cases for the TestUtils class.
28   *
29   * @version $Revision: 618114 $ $Date: 2008-02-03 15:48:38 -0700 (Sun, 03 Feb 2008) $
30   */
31  
32  public class TestUtilsTest extends TestCase {
33  
34      public TestUtilsTest(String name) {
35          super(name);
36      }
37  
38      public void setUp() {
39      }
40  
41      public static Test suite() {
42          TestSuite suite = new TestSuite(TestUtilsTest.class);
43          suite.setName("TestUtils Tests");
44          return suite;
45      }
46  
47      public void testChiSquare() throws Exception {
48          
49          // Target values computed using R version 1.8.1 
50          // Some assembly required ;-)  
51          //      Use sum((obs - exp)^2/exp) for the chi-square statistic and
52          //      1 - pchisq(sum((obs - exp)^2/exp), length(obs) - 1) for the p-value
53          
54          long[] observed = {10, 9, 11};
55          double[] expected = {10, 10, 10};
56          assertEquals("chi-square statistic", 0.2,  TestUtils.chiSquare(expected, observed), 10E-12);
57          assertEquals("chi-square p-value", 0.904837418036, TestUtils.chiSquareTest(expected, observed), 1E-10);
58          
59          long[] observed1 = { 500, 623, 72, 70, 31 };
60          double[] expected1 = { 485, 541, 82, 61, 37 };
61          assertEquals( "chi-square test statistic", 9.023307936427388, TestUtils.chiSquare(expected1, observed1), 1E-10);
62          assertEquals("chi-square p-value", 0.06051952647453607, TestUtils.chiSquareTest(expected1, observed1), 1E-9);
63          assertTrue("chi-square test reject", TestUtils.chiSquareTest(expected1, observed1, 0.07));
64          assertTrue("chi-square test accept", !TestUtils.chiSquareTest(expected1, observed1, 0.05));
65  
66          try {
67              TestUtils.chiSquareTest(expected1, observed1, 95);
68              fail("alpha out of range, IllegalArgumentException expected");
69          } catch (IllegalArgumentException ex) {
70              // expected
71          }  
72          
73          long[] tooShortObs = { 0 };
74          double[] tooShortEx = { 1 };
75          try {
76              TestUtils.chiSquare(tooShortEx, tooShortObs);
77              fail("arguments too short, IllegalArgumentException expected");
78          } catch (IllegalArgumentException ex) {
79              // expected
80          }
81  
82          // unmatched arrays
83          long[] unMatchedObs = { 0, 1, 2, 3 };
84          double[] unMatchedEx = { 1, 1, 2 };
85          try {
86              TestUtils.chiSquare(unMatchedEx, unMatchedObs);
87              fail("arrays have different lengths, IllegalArgumentException expected");
88          } catch (IllegalArgumentException ex) {
89              // expected
90          }
91          
92          // 0 expected count
93          expected[0] = 0;
94          try {
95              TestUtils.chiSquareTest(expected, observed, .01);
96              fail("bad expected count, IllegalArgumentException expected");
97          } catch (IllegalArgumentException ex) {
98              // expected
99          } 
100         
101         // negative observed count
102         expected[0] = 1;
103         observed[0] = -1;
104         try {
105             TestUtils.chiSquareTest(expected, observed, .01);
106             fail("bad expected count, IllegalArgumentException expected");
107         } catch (IllegalArgumentException ex) {
108             // expected
109         } 
110         
111     }
112 
113     public void testChiSquareIndependence() throws Exception {
114         
115         // Target values computed using R version 1.8.1 
116         
117         long[][] counts = { {40, 22, 43}, {91, 21, 28}, {60, 10, 22}};
118         assertEquals( "chi-square test statistic", 22.709027688, TestUtils.chiSquare(counts), 1E-9);
119         assertEquals("chi-square p-value", 0.000144751460134, TestUtils.chiSquareTest(counts), 1E-9);
120         assertTrue("chi-square test reject", TestUtils.chiSquareTest(counts, 0.0002));
121         assertTrue("chi-square test accept", !TestUtils.chiSquareTest(counts, 0.0001));    
122         
123         long[][] counts2 = {{10, 15}, {30, 40}, {60, 90} };
124         assertEquals( "chi-square test statistic", 0.168965517241, TestUtils.chiSquare(counts2), 1E-9);
125         assertEquals("chi-square p-value",0.918987499852, TestUtils.chiSquareTest(counts2), 1E-9);
126         assertTrue("chi-square test accept", !TestUtils.chiSquareTest(counts2, 0.1)); 
127         
128         // ragged input array
129         long[][] counts3 = { {40, 22, 43}, {91, 21, 28}, {60, 10}};
130         try {
131             TestUtils.chiSquare(counts3);
132             fail("Expecting IllegalArgumentException");
133         } catch (IllegalArgumentException ex) {
134             // expected
135         }
136         
137         // insufficient data
138         long[][] counts4 = {{40, 22, 43}};
139         try {
140             TestUtils.chiSquare(counts4);
141             fail("Expecting IllegalArgumentException");
142         } catch (IllegalArgumentException ex) {
143             // expected
144         } 
145         long[][] counts5 = {{40}, {40}, {30}, {10}};
146         try {
147             TestUtils.chiSquare(counts5);
148             fail("Expecting IllegalArgumentException");
149         } catch (IllegalArgumentException ex) {
150             // expected
151         } 
152         
153         // negative counts
154         long[][] counts6 = {{10, -2}, {30, 40}, {60, 90} };
155         try {
156             TestUtils.chiSquare(counts6);
157             fail("Expecting IllegalArgumentException");
158         } catch (IllegalArgumentException ex) {
159             // expected
160         } 
161         
162         // bad alpha
163         try {
164             TestUtils.chiSquareTest(counts, 0);
165             fail("Expecting IllegalArgumentException");
166         } catch (IllegalArgumentException ex) {
167             // expected
168         } 
169     }
170     
171     public void testChiSquareLargeTestStatistic() throws Exception {
172         double[] exp = new double[] {
173                 3389119.5, 649136.6, 285745.4, 25357364.76, 11291189.78, 543628.0, 
174                 232921.0, 437665.75
175         };
176 
177         long[] obs = new long[] {
178                 2372383, 584222, 257170, 17750155, 7903832, 489265, 209628, 393899
179         };
180         org.apache.commons.math.stat.inference.ChiSquareTestImpl csti =
181             new org.apache.commons.math.stat.inference.ChiSquareTestImpl(); 
182         double cst = csti.chiSquareTest(exp, obs); 
183         assertEquals("chi-square p-value", 0.0, cst, 1E-3);
184         assertEquals( "chi-square test statistic", 
185                 114875.90421929007, TestUtils.chiSquare(exp, obs), 1E-9);
186     }
187     
188     /** Contingency table containing zeros - PR # 32531 */
189     public void testChiSquareZeroCount() throws Exception {
190         // Target values computed using R version 1.8.1 
191         long[][] counts = { {40, 0, 4}, {91, 1, 2}, {60, 2, 0}};
192         assertEquals( "chi-square test statistic", 9.67444662263,
193                 TestUtils.chiSquare(counts), 1E-9);
194         assertEquals("chi-square p-value", 0.0462835770603,
195                 TestUtils.chiSquareTest(counts), 1E-9);       
196     }
197     
198     private double[] tooShortObs = { 1.0 };
199     private double[] emptyObs = {};
200     private SummaryStatistics emptyStats = new SummaryStatistics();  
201 
202     public void testOneSampleT() throws Exception {
203         double[] observed =
204             {93.0, 103.0, 95.0, 101.0, 91.0, 105.0, 96.0, 94.0, 101.0,  88.0, 98.0, 94.0, 101.0, 92.0, 95.0 };
205         double mu = 100.0;
206         SummaryStatistics sampleStats = null;
207         sampleStats = new SummaryStatistics();
208         for (int i = 0; i < observed.length; i++) {
209             sampleStats.addValue(observed[i]);
210         }
211 
212         // Target comparison values computed using R version 1.8.1 (Linux version)
213         assertEquals("t statistic",  -2.81976445346,
214                 TestUtils.t(mu, observed), 10E-10);
215         assertEquals("t statistic",  -2.81976445346,
216                 TestUtils.t(mu, sampleStats), 10E-10);
217         assertEquals("p value", 0.0136390585873,
218                 TestUtils.tTest(mu, observed), 10E-10);
219         assertEquals("p value", 0.0136390585873,
220                 TestUtils.tTest(mu, sampleStats), 10E-10);
221 
222         try {
223             TestUtils.t(mu, (double[]) null);
224             fail("arguments too short, IllegalArgumentException expected");
225         } catch (IllegalArgumentException ex) {
226             // expected
227         }
228 
229         try {
230             TestUtils.t(mu, (SummaryStatistics) null);
231             fail("arguments too short, IllegalArgumentException expected");
232         } catch (IllegalArgumentException ex) {
233             // expected
234         }
235 
236         try {
237             TestUtils.t(mu, emptyObs);
238             fail("arguments too short, IllegalArgumentException expected");
239         } catch (IllegalArgumentException ex) {
240             // expected
241         }
242         
243         try {
244             TestUtils.t(mu, emptyStats);
245             fail("arguments too short, IllegalArgumentException expected");
246         } catch (IllegalArgumentException ex) {
247             // expected
248         }
249 
250         try {
251             TestUtils.t(mu, tooShortObs);
252             fail("insufficient data to compute t statistic, IllegalArgumentException expected");
253         } catch (IllegalArgumentException ex) {
254             // expected
255         }
256         try {
257             TestUtils.tTest(mu, tooShortObs);
258             fail("insufficient data to perform t test, IllegalArgumentException expected");
259         } catch (IllegalArgumentException ex) {
260             // expected
261         }  
262 
263         try {
264             TestUtils.t(mu, (SummaryStatistics) null);
265             fail("insufficient data to compute t statistic, IllegalArgumentException expected");
266         } catch (IllegalArgumentException ex) {
267             // expected
268         }
269         try {
270             TestUtils.tTest(mu, (SummaryStatistics) null);
271             fail("insufficient data to perform t test, IllegalArgumentException expected");
272         } catch (IllegalArgumentException ex) {
273             // expected
274         }  
275     }
276     
277     public void testOneSampleTTest() throws Exception {
278         double[] oneSidedP =
279             {2d, 0d, 6d, 6d, 3d, 3d, 2d, 3d, -6d, 6d, 6d, 6d, 3d, 0d, 1d, 1d, 0d, 2d, 3d, 3d };
280         SummaryStatistics oneSidedPStats = new SummaryStatistics();    
281         for (int i = 0; i < oneSidedP.length; i++) {
282             oneSidedPStats.addValue(oneSidedP[i]);
283         }
284         // Target comparison values computed using R version 1.8.1 (Linux version)
285         assertEquals("one sample t stat", 3.86485535541, 
286                 TestUtils.t(0d, oneSidedP), 10E-10);
287         assertEquals("one sample t stat", 3.86485535541, 
288                 TestUtils.t(0d, oneSidedPStats),1E-10);
289         assertEquals("one sample p value", 0.000521637019637,
290                 TestUtils.tTest(0d, oneSidedP) / 2d, 10E-10);
291         assertEquals("one sample p value", 0.000521637019637,
292                 TestUtils.tTest(0d, oneSidedPStats) / 2d, 10E-5);
293         assertTrue("one sample t-test reject", TestUtils.tTest(0d, oneSidedP, 0.01));
294         assertTrue("one sample t-test reject", TestUtils.tTest(0d, oneSidedPStats, 0.01));
295         assertTrue("one sample t-test accept", !TestUtils.tTest(0d, oneSidedP, 0.0001));
296         assertTrue("one sample t-test accept", !TestUtils.tTest(0d, oneSidedPStats, 0.0001));
297         
298         try {
299             TestUtils.tTest(0d, oneSidedP, 95);
300             fail("alpha out of range, IllegalArgumentException expected");
301         } catch (IllegalArgumentException ex) {
302             // expected
303         }  
304         
305         try {
306             TestUtils.tTest(0d, oneSidedPStats, 95);
307             fail("alpha out of range, IllegalArgumentException expected");
308         } catch (IllegalArgumentException ex) {
309             // expected
310         }  
311         
312     }
313     
314     public void testTwoSampleTHeterscedastic() throws Exception {
315         double[] sample1 = { 7d, -4d, 18d, 17d, -3d, -5d, 1d, 10d, 11d, -2d };
316         double[] sample2 = { -1d, 12d, -1d, -3d, 3d, -5d, 5d, 2d, -11d, -1d, -3d };
317         SummaryStatistics sampleStats1 = new SummaryStatistics();  
318         for (int i = 0; i < sample1.length; i++) {
319             sampleStats1.addValue(sample1[i]);
320         }
321         SummaryStatistics sampleStats2 = new SummaryStatistics();    
322         for (int i = 0; i < sample2.length; i++) {
323             sampleStats2.addValue(sample2[i]);
324         }
325         
326         // Target comparison values computed using R version 1.8.1 (Linux version)
327         assertEquals("two sample heteroscedastic t stat", 1.60371728768, 
328                 TestUtils.t(sample1, sample2), 1E-10);
329         assertEquals("two sample heteroscedastic t stat", 1.60371728768, 
330                 TestUtils.t(sampleStats1, sampleStats2), 1E-10);
331         assertEquals("two sample heteroscedastic p value", 0.128839369622, 
332                 TestUtils.tTest(sample1, sample2), 1E-10);
333         assertEquals("two sample heteroscedastic p value", 0.128839369622, 
334                 TestUtils.tTest(sampleStats1, sampleStats2), 1E-10);     
335         assertTrue("two sample heteroscedastic t-test reject", 
336                 TestUtils.tTest(sample1, sample2, 0.2));
337         assertTrue("two sample heteroscedastic t-test reject", 
338                 TestUtils.tTest(sampleStats1, sampleStats2, 0.2));
339         assertTrue("two sample heteroscedastic t-test accept", 
340                 !TestUtils.tTest(sample1, sample2, 0.1));
341         assertTrue("two sample heteroscedastic t-test accept", 
342                 !TestUtils.tTest(sampleStats1, sampleStats2, 0.1));
343         
344         try {
345             TestUtils.tTest(sample1, sample2, .95);
346             fail("alpha out of range, IllegalArgumentException expected");
347         } catch (IllegalArgumentException ex) {
348             // expected
349         } 
350         
351         try {
352             TestUtils.tTest(sampleStats1, sampleStats2, .95);
353             fail("alpha out of range, IllegalArgumentException expected");
354         } catch (IllegalArgumentException ex) {
355             // expected 
356         }  
357         
358         try {
359             TestUtils.tTest(sample1, tooShortObs, .01);
360             fail("insufficient data, IllegalArgumentException expected");
361         } catch (IllegalArgumentException ex) {
362             // expected
363         }  
364         
365         try {
366             TestUtils.tTest(sampleStats1, (SummaryStatistics) null, .01);
367             fail("insufficient data, IllegalArgumentException expected");
368         } catch (IllegalArgumentException ex) {
369             // expected
370         }  
371         
372         try {
373             TestUtils.tTest(sample1, tooShortObs);
374             fail("insufficient data, IllegalArgumentException expected");
375         } catch (IllegalArgumentException ex) {
376             // expected
377         }  
378         
379         try {
380             TestUtils.tTest(sampleStats1, (SummaryStatistics) null);
381             fail("insufficient data, IllegalArgumentException expected");
382         } catch (IllegalArgumentException ex) {
383             // expected
384         }  
385         
386         try {
387             TestUtils.t(sample1, tooShortObs);
388             fail("insufficient data, IllegalArgumentException expected");
389         } catch (IllegalArgumentException ex) {
390             // expected
391         }
392         
393         try {
394             TestUtils.t(sampleStats1, (SummaryStatistics) null);
395             fail("insufficient data, IllegalArgumentException expected");
396         } catch (IllegalArgumentException ex) {
397             // expected
398         }
399     }
400     public void testTwoSampleTHomoscedastic() throws Exception {
401         double[] sample1 ={2, 4, 6, 8, 10, 97};
402         double[] sample2 = {4, 6, 8, 10, 16};
403         SummaryStatistics sampleStats1 = new SummaryStatistics();  
404         for (int i = 0; i < sample1.length; i++) {
405             sampleStats1.addValue(sample1[i]);
406         }
407         SummaryStatistics sampleStats2 = new SummaryStatistics();    
408         for (int i = 0; i < sample2.length; i++) {
409             sampleStats2.addValue(sample2[i]);
410         }
411         
412         // Target comparison values computed using R version 1.8.1 (Linux version)
413         assertEquals("two sample homoscedastic t stat", 0.73096310086, 
414                 TestUtils.homoscedasticT(sample1, sample2), 10E-11);
415         assertEquals("two sample homoscedastic p value", 0.4833963785, 
416                 TestUtils.homoscedasticTTest(sampleStats1, sampleStats2), 1E-10);     
417         assertTrue("two sample homoscedastic t-test reject", 
418                 TestUtils.homoscedasticTTest(sample1, sample2, 0.49));
419         assertTrue("two sample homoscedastic t-test accept", 
420                 !TestUtils.homoscedasticTTest(sample1, sample2, 0.48));
421     }
422     
423     public void testSmallSamples() throws Exception {
424         double[] sample1 = {1d, 3d};
425         double[] sample2 = {4d, 5d};        
426         
427         // Target values computed using R, version 1.8.1 (linux version)
428         assertEquals(-2.2360679775, TestUtils.t(sample1, sample2),
429                 1E-10);
430         assertEquals(0.198727388935, TestUtils.tTest(sample1, sample2),
431                 1E-10);
432     }
433     
434     public void testPaired() throws Exception {
435         double[] sample1 = {1d, 3d, 5d, 7d};
436         double[] sample2 = {0d, 6d, 11d, 2d};
437         double[] sample3 = {5d, 7d, 8d, 10d};
438 
439         // Target values computed using R, version 1.8.1 (linux version)
440         assertEquals(-0.3133, TestUtils.pairedT(sample1, sample2), 1E-4);
441         assertEquals(0.774544295819, TestUtils.pairedTTest(sample1, sample2), 1E-10);
442         assertEquals(0.001208, TestUtils.pairedTTest(sample1, sample3), 1E-6);
443         assertFalse(TestUtils.pairedTTest(sample1, sample3, .001));
444         assertTrue(TestUtils.pairedTTest(sample1, sample3, .002));    
445     }
446     
447     private double[] classA =
448       {93.0, 103.0, 95.0, 101.0};
449     private double[] classB =
450       {99.0, 92.0, 102.0, 100.0, 102.0};
451     private double[] classC =
452       {110.0, 115.0, 111.0, 117.0, 128.0};
453     
454     private List classes = new ArrayList();
455     private OneWayAnova oneWayAnova = new OneWayAnovaImpl();
456     
457     public void testOneWayAnovaUtils() throws Exception {
458         classes.add(classA);
459         classes.add(classB);
460         classes.add(classC);
461         assertEquals(oneWayAnova.anovaFValue(classes), 
462                 TestUtils.oneWayAnovaFValue(classes), 10E-12);
463         assertEquals(oneWayAnova.anovaPValue(classes), 
464                 TestUtils.oneWayAnovaPValue(classes), 10E-12);
465         assertEquals(oneWayAnova.anovaTest(classes, 0.01), 
466                 TestUtils.oneWayAnovaTest(classes, 0.01));   
467     } 
468 }