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