001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.stat.inference;
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import junit.framework.Test;
023    import junit.framework.TestCase;
024    import junit.framework.TestSuite;
025    import org.apache.commons.math.stat.descriptive.SummaryStatistics;
026    /**
027     * Test cases for the TestUtils class.
028     *
029     * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
030     */
031    
032    public class TestUtilsTest extends TestCase {
033    
034        public TestUtilsTest(String name) {
035            super(name);
036        }
037    
038        public static Test suite() {
039            TestSuite suite = new TestSuite(TestUtilsTest.class);
040            suite.setName("TestUtils Tests");
041            return suite;
042        }
043    
044        public void testChiSquare() throws Exception {
045            
046            // Target values computed using R version 1.8.1 
047            // Some assembly required ;-)  
048            //      Use sum((obs - exp)^2/exp) for the chi-square statistic and
049            //      1 - pchisq(sum((obs - exp)^2/exp), length(obs) - 1) for the p-value
050            
051            long[] observed = {10, 9, 11};
052            double[] expected = {10, 10, 10};
053            assertEquals("chi-square statistic", 0.2,  TestUtils.chiSquare(expected, observed), 10E-12);
054            assertEquals("chi-square p-value", 0.904837418036, TestUtils.chiSquareTest(expected, observed), 1E-10);
055            
056            long[] observed1 = { 500, 623, 72, 70, 31 };
057            double[] expected1 = { 485, 541, 82, 61, 37 };
058            assertEquals( "chi-square test statistic", 9.023307936427388, TestUtils.chiSquare(expected1, observed1), 1E-10);
059            assertEquals("chi-square p-value", 0.06051952647453607, TestUtils.chiSquareTest(expected1, observed1), 1E-9);
060            assertTrue("chi-square test reject", TestUtils.chiSquareTest(expected1, observed1, 0.07));
061            assertTrue("chi-square test accept", !TestUtils.chiSquareTest(expected1, observed1, 0.05));
062    
063            try {
064                TestUtils.chiSquareTest(expected1, observed1, 95);
065                fail("alpha out of range, IllegalArgumentException expected");
066            } catch (IllegalArgumentException ex) {
067                // expected
068            }  
069            
070            long[] tooShortObs = { 0 };
071            double[] tooShortEx = { 1 };
072            try {
073                TestUtils.chiSquare(tooShortEx, tooShortObs);
074                fail("arguments too short, IllegalArgumentException expected");
075            } catch (IllegalArgumentException ex) {
076                // expected
077            }
078    
079            // unmatched arrays
080            long[] unMatchedObs = { 0, 1, 2, 3 };
081            double[] unMatchedEx = { 1, 1, 2 };
082            try {
083                TestUtils.chiSquare(unMatchedEx, unMatchedObs);
084                fail("arrays have different lengths, IllegalArgumentException expected");
085            } catch (IllegalArgumentException ex) {
086                // expected
087            }
088            
089            // 0 expected count
090            expected[0] = 0;
091            try {
092                TestUtils.chiSquareTest(expected, observed, .01);
093                fail("bad expected count, IllegalArgumentException expected");
094            } catch (IllegalArgumentException ex) {
095                // expected
096            } 
097            
098            // negative observed count
099            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    }