    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: 1.1 $ $Date: 2004/10/08 05:08:19 $
    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