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.util.FastMath;
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.assertFalse;
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 GTest class.
35   *
36   * Data for the tests are from p64-69 in: McDonald, J.H. 2009. Handbook of
37   * Biological Statistics (2nd ed.). Sparky House Publishing, Baltimore,
38   * Maryland.
39   *
40   */
41  class GTestTest {
42  
43      protected GTest testStatistic = new GTest();
44  
45      @Test
46      void testGTestGoodnesOfFit1() throws Exception {
47          final double[] exp = new double[]{
48              3d, 1d
49          };
50  
51          final long[] obs = new long[]{
52              423, 133
53          };
54  
55          assertEquals(0.348721, testStatistic.g(exp, obs), 1E-6, "G test statistic");
56          final double p_gtgf = testStatistic.gTest(exp, obs);
57          assertEquals(0.55483, p_gtgf, 1E-5, "g-Test p-value");
58  
59          assertFalse(testStatistic.gTest(exp, obs, 0.05));
60      }
61  
62      @Test
63      void testGTestGoodnesOfFit2() throws Exception {
64          final double[] exp = new double[]{
65              0.54d, 0.40d, 0.05d, 0.01d
66          };
67  
68          final long[] obs = new long[]{
69              70, 79, 3, 4
70          };
71          assertEquals(13.144799, testStatistic.g(exp, obs), 1E-6, "G test statistic");
72          final double p_gtgf = testStatistic.gTest(exp, obs);
73          assertEquals(0.004333, p_gtgf, 1E-5, "g-Test p-value");
74  
75          assertTrue(testStatistic.gTest(exp, obs, 0.05));
76      }
77  
78      @Test
79      void testGTestGoodnesOfFit3() throws Exception {
80          final double[] exp = new double[]{
81              0.167d, 0.483d, 0.350d
82          };
83  
84          final long[] obs = new long[]{
85              14, 21, 25
86          };
87  
88          assertEquals(4.5554, testStatistic.g(exp, obs), 1E-4, "G test statistic");
89          // Intrinisic (Hardy-Weinberg proportions) P-Value should be 0.033
90          final double p_gtgf = testStatistic.gTestIntrinsic(exp, obs);
91          assertEquals(0.0328, p_gtgf, 1E-4, "g-Test p-value");
92  
93          assertFalse(testStatistic.gTest(exp, obs, 0.05));
94      }
95  
96      @Test
97      void testGTestIndependance1() throws Exception {
98          final long[] obs1 = new long[]{
99              268, 199, 42
100         };
101 
102         final long[] obs2 = new long[]{
103             807, 759, 184
104         };
105 
106         final double g = testStatistic.gDataSetsComparison(obs1, obs2);
107 
108         assertEquals(7.3008170, g, 1E-6, "G test statistic");
109         final double p_gti = testStatistic.gTestDataSetsComparison(obs1, obs2);
110 
111         assertEquals(0.0259805, p_gti, 1E-6, "g-Test p-value");
112         assertTrue(testStatistic.gTestDataSetsComparison(obs1, obs2, 0.05));
113     }
114 
115     @Test
116     void testGTestIndependance2() throws Exception {
117         final long[] obs1 = new long[]{
118             127, 99, 264
119         };
120 
121         final long[] obs2 = new long[]{
122             116, 67, 161
123         };
124 
125         final double g = testStatistic.gDataSetsComparison(obs1, obs2);
126 
127         assertEquals(6.227288, g, 1E-6, "G test statistic");
128         final double p_gti = testStatistic.gTestDataSetsComparison(obs1, obs2);
129 
130         assertEquals(0.04443, p_gti, 1E-5, "g-Test p-value");
131         assertTrue(testStatistic.gTestDataSetsComparison(obs1, obs2, 0.05));
132     }
133 
134     @Test
135     void testGTestIndependance3() throws Exception {
136         final long[] obs1 = new long[]{
137             190, 149
138         };
139 
140         final long[] obs2 = new long[]{
141             42, 49
142         };
143 
144         final double g = testStatistic.gDataSetsComparison(obs1, obs2);
145         assertEquals(2.8187, g, 1E-4, "G test statistic");
146         final double p_gti = testStatistic.gTestDataSetsComparison(obs1, obs2);
147         assertEquals(0.09317325, p_gti, 1E-6, "g-Test p-value");
148 
149         assertFalse(testStatistic.gTestDataSetsComparison(obs1, obs2, 0.05));
150     }
151 
152     @Test
153     void testGTestSetsComparisonBadCounts() {
154         long[] observed1 = {10, -1, 12, 10, 15};
155         long[] observed2 = {15, 10, 10, 15, 5};
156         try {
157             testStatistic.gTestDataSetsComparison(
158                     observed1, observed2);
159             fail("Expecting MathIllegalArgumentException - negative count");
160         } catch (MathIllegalArgumentException ex) {
161             // expected
162         }
163         long[] observed3 = {10, 0, 12, 10, 15};
164         long[] observed4 = {15, 0, 10, 15, 5};
165         try {
166             testStatistic.gTestDataSetsComparison(
167                     observed3, observed4);
168             fail("Expecting MathIllegalArgumentException - double 0's");
169         } catch (MathIllegalArgumentException ex) {
170             // expected
171         }
172         long[] observed5 = {10, 10, 12, 10, 15};
173         long[] observed6 = {0, 0, 0, 0, 0};
174         try {
175             testStatistic.gTestDataSetsComparison(
176                     observed5, observed6);
177             fail("Expecting MathIllegalArgumentException - vanishing counts");
178         } catch (MathIllegalArgumentException ex) {
179             // expected
180         }
181     }
182 
183     @Test
184     void testUnmatchedArrays() {
185         final long[] observed = { 0, 1, 2, 3 };
186         final double[] expected = { 1, 1, 2 };
187         final long[] observed2 = {3, 4};
188         try {
189             testStatistic.gTest(expected, observed);
190             fail("arrays have different lengths, MathIllegalArgumentException expected");
191         } catch (MathIllegalArgumentException ex) {
192             // expected
193         }
194         try {
195             testStatistic.gTestDataSetsComparison(observed, observed2);
196             fail("arrays have different lengths, MathIllegalArgumentException expected");
197         } catch (MathIllegalArgumentException ex) {
198             // expected
199         }
200     }
201 
202     @Test
203     void testNegativeObservedCounts() {
204         final long[] observed = { 0, 1, 2, -3 };
205         final double[] expected = { 1, 1, 2, 3};
206         final long[] observed2 = {3, 4, 5, 0};
207         try {
208             testStatistic.gTest(expected, observed);
209             fail("negative observed count, MathIllegalArgumentException expected");
210         } catch (MathIllegalArgumentException ex) {
211             // expected
212         }
213         try {
214             testStatistic.gTestDataSetsComparison(observed, observed2);
215             fail("negative observed count, MathIllegalArgumentException expected");
216         } catch (MathIllegalArgumentException ex) {
217             // expected
218         }
219     }
220 
221     @Test
222     void testZeroExpectedCounts() {
223         final long[] observed = { 0, 1, 2, -3 };
224         final double[] expected = { 1, 0, 2, 3};
225         try {
226             testStatistic.gTest(expected, observed);
227             fail("zero expected count, MathIllegalArgumentException expected");
228         } catch (MathIllegalArgumentException ex) {
229             // expected
230         }
231     }
232 
233     @Test
234     void testBadAlpha() {
235         final long[] observed = { 0, 1, 2, 3 };
236         final double[] expected = { 1, 2, 2, 3};
237         final long[] observed2 = { 0, 2, 2, 3 };
238         try {
239             testStatistic.gTest(expected, observed, 0.8);
240             fail("zero expected count, MathIllegalArgumentException expected");
241         } catch (MathIllegalArgumentException ex) {
242             // expected
243         }
244         try {
245             testStatistic.gTestDataSetsComparison(observed, observed2, -0.5);
246             fail("zero expected count, MathIllegalArgumentException expected");
247         } catch (MathIllegalArgumentException ex) {
248             // expected
249         }
250     }
251 
252     @Test
253     void testScaling() {
254       final long[] observed = {9, 11, 10, 8, 12};
255       final double[] expected1 = {10, 10, 10, 10, 10};
256       final double[] expected2 = {1000, 1000, 1000, 1000, 1000};
257       final double[] expected3 = {1, 1, 1, 1, 1};
258       final double tol = 1E-15;
259       assertEquals(
260               testStatistic.gTest(expected1, observed),
261               testStatistic.gTest(expected2, observed),
262               tol);
263       assertEquals(
264               testStatistic.gTest(expected1, observed),
265               testStatistic.gTest(expected3, observed),
266               tol);
267     }
268 
269     @Test
270     void testRootLogLikelihood() {
271         // positive where k11 is bigger than expected.
272         assertTrue(testStatistic.rootLogLikelihoodRatio(904, 21060, 1144, 283012) > 0.0);
273 
274         // negative because k11 is lower than expected
275         assertTrue(testStatistic.rootLogLikelihoodRatio(36, 21928, 60280, 623876) < 0.0);
276 
277         assertEquals(FastMath.sqrt(2.772589), testStatistic.rootLogLikelihoodRatio(1, 0, 0, 1), 0.000001);
278         assertEquals(-FastMath.sqrt(2.772589), testStatistic.rootLogLikelihoodRatio(0, 1, 1, 0), 0.000001);
279         assertEquals(FastMath.sqrt(27.72589), testStatistic.rootLogLikelihoodRatio(10, 0, 0, 10), 0.00001);
280 
281         assertEquals(FastMath.sqrt(39.33052), testStatistic.rootLogLikelihoodRatio(5, 1995, 0, 100000), 0.00001);
282         assertEquals(-FastMath.sqrt(39.33052), testStatistic.rootLogLikelihoodRatio(0, 100000, 5, 1995), 0.00001);
283 
284         assertEquals(FastMath.sqrt(4730.737), testStatistic.rootLogLikelihoodRatio(1000, 1995, 1000, 100000), 0.001);
285         assertEquals(-FastMath.sqrt(4730.737), testStatistic.rootLogLikelihoodRatio(1000, 100000, 1000, 1995), 0.001);
286 
287         assertEquals(FastMath.sqrt(5734.343), testStatistic.rootLogLikelihoodRatio(1000, 1000, 1000, 100000), 0.001);
288         assertEquals(FastMath.sqrt(5714.932), testStatistic.rootLogLikelihoodRatio(1000, 1000, 1000, 99000), 0.001);
289     }
290 }