1   /*
2    * Copyright 2003-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.math.stat.descriptive;
17  
18  import junit.framework.Test;
19  import junit.framework.TestCase;
20  import junit.framework.TestSuite;
21  
22  import org.apache.commons.math.TestUtils;
23  import org.apache.commons.math.random.RandomData;
24  import org.apache.commons.math.random.RandomDataImpl;
25  
26  /**
27   * Test cases for the {@link Univariate} class.
28   *
29   * @version $Revision: 201916 $ $Date: 2005-06-26 15:25:41 -0700 (Sun, 26 Jun 2005) $
30   */
31  
32  public final class DescriptiveStatisticsTest extends TestCase {
33      private double one = 1;
34      private float two = 2;
35      private int three = 3;
36      private double mean = 2;
37      private double sumSq = 18;
38      private double sum = 8;
39      private double var = 0.666666666666666666667;
40      private double std = Math.sqrt(var);
41      private double n = 4;
42      private double min = 1;
43      private double max = 3;
44      private double skewness = 0;
45      private double kurtosis = 0.5;
46      private double tolerance = 10E-15;
47      
48      public DescriptiveStatisticsTest(String name) {
49          super(name);
50      }
51      
52      public void setUp() {  
53      }
54      
55      public static Test suite() {
56          TestSuite suite = new TestSuite(DescriptiveStatisticsTest.class);
57          suite.setName("Descriptive Statistics Tests");
58          return suite;
59      }
60      
61      /** test stats */
62      public void testStats() {
63          DescriptiveStatistics u = DescriptiveStatistics.newInstance(); 
64          assertEquals("total count",0,u.getN(),tolerance);
65          u.addValue(one);
66          u.addValue(two);
67          u.addValue(two);
68          u.addValue(three);
69          assertEquals("N",n,u.getN(),tolerance);
70          assertEquals("sum",sum,u.getSum(),tolerance);
71          assertEquals("sumsq",sumSq,u.getSumsq(),tolerance);
72          assertEquals("var",var,u.getVariance(),tolerance);
73          assertEquals("std",std,u.getStandardDeviation(),tolerance);
74          assertEquals("mean",mean,u.getMean(),tolerance);
75          assertEquals("min",min,u.getMin(),tolerance);
76          assertEquals("max",max,u.getMax(),tolerance);
77          u.clear();
78          assertEquals("total count",0,u.getN(),tolerance);    
79      }     
80      
81      public void testN0andN1Conditions() throws Exception {
82          DescriptiveStatistics u = DescriptiveStatistics.newInstance();
83                  
84              assertTrue("Mean of n = 0 set should be NaN", 
85                  Double.isNaN( u.getMean() ) );
86              assertTrue("Standard Deviation of n = 0 set should be NaN", 
87                  Double.isNaN( u.getStandardDeviation() ) );
88              assertTrue("Variance of n = 0 set should be NaN",
89                  Double.isNaN(u.getVariance() ) );
90  
91              u.addValue(one);
92  
93              assertTrue( "Mean of n = 1 set should be value of single item n1",
94                  u.getMean() == one);
95              assertTrue( "StdDev of n = 1 set should be zero, instead it is: " 
96                  + u.getStandardDeviation(), u.getStandardDeviation() == 0);
97              assertTrue( "Variance of n = 1 set should be zero", 
98                  u.getVariance() == 0);  
99      }
100     
101     public void testSkewAndKurtosis() {
102         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
103         
104         double[] testArray = 
105         { 12.5, 12, 11.8, 14.2, 14.9, 14.5, 21, 8.2, 10.3, 11.3, 14.1,
106           9.9, 12.2, 12, 12.1, 11, 19.8, 11, 10, 8.8, 9, 12.3 };
107         for( int i = 0; i < testArray.length; i++) {
108             u.addValue( testArray[i]);
109         }
110         
111         assertEquals("mean", 12.40455, u.getMean(), 0.0001);
112         assertEquals("variance", 10.00236, u.getVariance(), 0.0001);
113         assertEquals("skewness", 1.437424, u.getSkewness(), 0.0001);
114         assertEquals("kurtosis", 2.37719, u.getKurtosis(), 0.0001);
115     }
116 
117     public void testProductAndGeometricMean() throws Exception {
118         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
119         u.setWindowSize(10);
120                 
121         u.addValue( 1.0 );
122         u.addValue( 2.0 );
123         u.addValue( 3.0 );
124         u.addValue( 4.0 );
125 
126         //assertEquals( "Product not expected", 
127         //    24.0, u.getProduct(), Double.MIN_VALUE );
128         assertEquals( "Geometric mean not expected", 
129             2.213364, u.getGeometricMean(), 0.00001 );
130 
131         // Now test rolling - StorelessDescriptiveStatistics should discount the contribution
132         // of a discarded element
133         for( int i = 0; i < 10; i++ ) {
134             u.addValue( i + 2 );
135         }
136         // Values should be (2,3,4,5,6,7,8,9,10,11)
137         
138         //assertEquals( "Product not expected", 39916800.0, 
139         //    u.getProduct(), 0.00001 );
140         assertEquals( "Geometric mean not expected", 5.755931, 
141             u.getGeometricMean(), 0.00001 );
142     }
143     
144     public void testAddValue() {
145         double[] test1 = {5,4,3,2,1,0};
146         double[] test2 = {5,2,1,0,4,3};
147 
148         DescriptiveStatistics stats = DescriptiveStatistics.newInstance();
149         stats.setWindowSize(12);
150         
151         for(int i = 0; i < test1.length; i++){
152             stats.addValue(test1[i]);
153         }     
154         
155         double[] test3 = stats.getValues();
156         
157         for(int i = 0; i < 6; i++){
158             assertEquals( "Added value ["+i+"] not equal", 
159             test3[i], test1[i],0.0);
160             //System.out.println(test3[i] + " "+test1[i]);
161         }     
162                 
163         for(int i = 0; i < test2.length; i++){
164             stats.addValue(test2[i]);
165         }     
166  
167         test3 = stats.getValues();  
168         
169         for(int i = 6; i < 12; i++){
170             assertEquals( "Added value ["+i+"] not equal", 
171             test3[i], test2[i-6],0.0);
172             //System.out.println(test3[i] + " "+test2[i-6]);
173         }    
174         
175         for(int i = 0; i < test2.length; i++){
176             stats.addValue(test2[i]);
177         }     
178  
179         test3 = stats.getValues();  
180         
181         for(int i = 0; i < 6; i++){
182             assertEquals( "Added value ["+i+"] not equal", 
183             test3[i], test2[i],0.0);
184             //System.out.println(test3[i] + " "+test2[i]);
185         }  
186         
187         for(int i = 6; i < 12; i++){
188             assertEquals( "Added value ["+i+"] not equal", 
189             test3[i], test2[i-6],0.0);
190             //System.out.println(test3[i] + " "+test2[i-6]);
191         }  
192          
193     }
194     
195     public void testGetSortedValues() {
196         double[] test1 = {5,4,3,2,1};
197         double[] test2 = {5,2,1,3,4,0};
198         double[] test3 = {1};
199         int[] testi = null;
200         double[] test4 = null;
201         RandomData rd = new RandomDataImpl();
202         tstGetSortedValues(test1);
203         tstGetSortedValues(test2);
204         tstGetSortedValues(test3);
205         for (int i = 0; i < 10; i++) {
206             testi = rd.nextPermutation(10,6);
207             test4 = new double[6];
208             for (int j = 0; j < testi.length; j++) {
209                 test4[j] = (double) testi[j];
210             }
211             tstGetSortedValues(test4);
212         }
213         for (int i = 0; i < 10; i++) {
214             testi = rd.nextPermutation(10,5);
215             test4 = new double[5];
216             for (int j = 0; j < testi.length; j++) {
217                 test4[j] = (double) testi[j];
218             }
219             tstGetSortedValues(test4);
220         }        
221     }
222     
223         
224         
225     private void tstGetSortedValues(double[] test) {
226         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
227         u.setWindowSize(test.length);
228         for (int i = 0; i < test.length; i++) {
229             u.addValue(test[i]);
230         }
231         double[] sorted = u.getSortedValues();
232         if (sorted.length != test.length) {
233             fail("wrong length for sorted values array");
234         }
235         for (int i = 0; i < sorted.length-1; i++) {
236             if (sorted[i] > sorted[i+1]) {
237                 fail("sorted values out of sequence");
238             }
239         }
240     }
241     
242     public void testPercentiles() {
243         double[] test = {5,4,3,2,1};
244         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
245         u.setWindowSize(110);
246         for (int i = 0; i < test.length; i++) {
247             u.addValue(test[i]);
248         }
249         assertEquals("expecting min",1,u.getPercentile(5),10E-12);
250         assertEquals("expecting max",5,u.getPercentile(99),10E-12);
251         assertEquals("expecting middle",3,u.getPercentile(50),10E-12);
252         try {
253             double x = u.getPercentile(0);
254             fail("expecting IllegalArgumentException for getPercentile(0)");
255         } catch (IllegalArgumentException ex) {
256             ;
257         }
258         try {
259             double x = u.getPercentile(120);
260             fail("expecting IllegalArgumentException for getPercentile(120)");
261         } catch (IllegalArgumentException ex) {
262             ;
263         }
264         
265         u.clear();
266         double[] test2 = {1,2,3,4};
267         for (int i = 0; i < test2.length; i++) {
268             u.addValue(test2[i]);
269         }
270         assertEquals("Q1",1.25,u.getPercentile(25),10E-12);
271         assertEquals("Q3",3.75,u.getPercentile(75),10E-12);
272         assertEquals("Q2",2.5,u.getPercentile(50),10E-12);
273         
274         u.clear();
275         double[] test3 = {1};
276         for (int i = 0; i < test3.length; i++) {
277             u.addValue(test3[i]);
278         }
279         assertEquals("Q1",1,u.getPercentile(25),10E-12);
280         assertEquals("Q3",1,u.getPercentile(75),10E-12);
281         assertEquals("Q2",1,u.getPercentile(50),10E-12);
282         
283         u.clear();
284         RandomData rd = new RandomDataImpl();
285         int[] testi = rd.nextPermutation(100,100); // will contain 0-99
286         for (int j = 0; j < testi.length; j++) {
287             u.addValue((double) testi[j]);  //OK, laugh at me for the cast
288         }
289         for (int i = 1; i < 100; i++) {
290             assertEquals("percentile " + i,
291                 (double) i-1 + (double) i*(.01), u.getPercentile(i),10E-12);
292         }
293         
294         u.clear();
295         double[] test4 = {1,2,3,4,100};
296         for (int i = 0; i < test4.length; i++) {
297             u.addValue(test4[i]);
298         }
299         assertEquals("80th",80.8,u.getPercentile(80),10E-12);
300         
301         u.clear();
302         assertTrue("empty value set should return NaN",
303             Double.isNaN(u.getPercentile(50)));
304     }
305                       
306     /** test stats */
307     public void testSerialization() {
308         DescriptiveStatistics u = DescriptiveStatistics.newInstance(); 
309         assertEquals("total count",0,u.getN(),tolerance);
310         u.addValue(one);
311         u.addValue(two);
312         
313         DescriptiveStatistics u2 = (DescriptiveStatistics)TestUtils.serializeAndRecover(u); 
314  
315         u2.addValue(two);
316         u2.addValue(three);
317         
318         assertEquals("N",n,u2.getN(),tolerance);
319         assertEquals("sum",sum,u2.getSum(),tolerance);
320         assertEquals("sumsq",sumSq,u2.getSumsq(),tolerance);
321         assertEquals("var",var,u2.getVariance(),tolerance);
322         assertEquals("std",std,u2.getStandardDeviation(),tolerance);
323         assertEquals("mean",mean,u2.getMean(),tolerance);
324         assertEquals("min",min,u2.getMin(),tolerance);
325         assertEquals("max",max,u2.getMax(),tolerance);
326 
327         u2.clear();
328         assertEquals("total count",0,u2.getN(),tolerance);    
329     }       
330 
331     public void testNewInstanceClassNull() {
332         try {
333             DescriptiveStatistics u = DescriptiveStatistics.newInstance((Class)null);
334             fail("null is not a valid descriptive statistics class");
335         } catch (NullPointerException ex) {
336             // success
337         } catch (Exception ex) {
338             fail();
339         }
340         
341     }
342     
343     public void testNewInstanceClassValid() {
344         try {
345             DescriptiveStatistics u = DescriptiveStatistics.newInstance(
346                 DescriptiveStatisticsImpl.class);
347             assertNotNull(u);
348             assertTrue(u instanceof DescriptiveStatisticsImpl);
349         } catch (Exception ex) {
350             fail();
351         }
352     }
353     
354     public void testWindowSize() {
355         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
356         u.setWindowSize(1234);
357         assertEquals(1234, u.getWindowSize());
358         
359         u.addValue(1.0);
360         u.addValue(2.0);
361         u.addValue(3.0);
362         u.addValue(4.0);
363         u.addValue(5.0);
364         assertEquals(5, u.getN());
365         
366         u.setWindowSize(DescriptiveStatistics.INFINITE_WINDOW);
367         assertEquals(5, u.getN());
368     }
369     
370     public void testWindowing() {
371         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
372         u.setWindowSize(2);
373         
374         u.addValue(1.0);
375         assertEquals(1.0, u.getMean(), tolerance);
376         
377         u.addValue(2.0);
378         assertEquals(1.5, u.getMean(), tolerance);
379         
380         u.addValue(3.0);
381         assertEquals(2.5, u.getMean(), tolerance);
382         
383         u.setWindowSize(1);
384         assertEquals(3.0, u.getMean(), tolerance);
385     }
386     
387     public void testToString() {
388         DescriptiveStatistics u = DescriptiveStatistics.newInstance();
389         assertTrue(u.toString().indexOf("NaN") > 0);  
390         assertTrue(u.toString().startsWith("DescriptiveStatistics"));
391         double[] testArray = 
392             { 12.5, 12, 11.8, 14.2, 14.9, 14.5, 21, 8.2, 10.3, 11.3, 14.1,
393                 9.9, 12.2, 12, 12.1, 11, 19.8, 11, 10, 8.8, 9, 12.3 };
394         for( int i = 0; i < testArray.length; i++) {
395             u.addValue( testArray[i]);
396         }        
397         assertTrue(u.toString().indexOf("NaN") == -1);  
398         assertTrue(u.toString().startsWith("DescriptiveStatistics"));
399     }
400     
401 }
402