001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with this 004 * work for additional information regarding copyright ownership. The ASF 005 * licenses this file to You under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law 009 * or agreed to in writing, software distributed under the License is 010 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 011 * KIND, either express or implied. See the License for the specific language 012 * governing permissions and limitations under the License. 013 */ 014 package org.apache.commons.math.stat.descriptive; 015 016 import java.util.Locale; 017 018 import junit.framework.Test; 019 import junit.framework.TestCase; 020 import junit.framework.TestSuite; 021 022 import org.apache.commons.math.stat.descriptive.rank.Percentile; 023 import org.apache.commons.math.util.MathUtils; 024 025 /** 026 * Test cases for the DescriptiveStatistics class. 027 * 028 * @version $Revision: 797742 $ $Date: 2007-08-16 15:36:33 -0500 (Thu, 16 Aug 029 * 2007) $ 030 */ 031 public class DescriptiveStatisticsTest extends TestCase { 032 033 public DescriptiveStatisticsTest(String name) { 034 super(name); 035 } 036 037 public static Test suite() { 038 TestSuite suite = new TestSuite(DescriptiveStatisticsTest.class); 039 suite.setName("DescriptiveStatistics Tests"); 040 return suite; 041 } 042 043 protected DescriptiveStatistics createDescriptiveStatistics() { 044 return new DescriptiveStatistics(); 045 } 046 047 public void testSetterInjection() { 048 DescriptiveStatistics stats = createDescriptiveStatistics(); 049 stats.addValue(1); 050 stats.addValue(3); 051 assertEquals(2, stats.getMean(), 1E-10); 052 // Now lets try some new math 053 stats.setMeanImpl(new deepMean()); 054 assertEquals(42, stats.getMean(), 1E-10); 055 } 056 057 public void testCopy() { 058 DescriptiveStatistics stats = createDescriptiveStatistics(); 059 stats.addValue(1); 060 stats.addValue(3); 061 DescriptiveStatistics copy = new DescriptiveStatistics(stats); 062 assertEquals(2, copy.getMean(), 1E-10); 063 // Now lets try some new math 064 stats.setMeanImpl(new deepMean()); 065 copy = stats.copy(); 066 assertEquals(42, copy.getMean(), 1E-10); 067 } 068 069 public void testWindowSize() { 070 DescriptiveStatistics stats = createDescriptiveStatistics(); 071 stats.setWindowSize(300); 072 for (int i = 0; i < 100; ++i) { 073 stats.addValue(i + 1); 074 } 075 int refSum = (100 * 101) / 2; 076 assertEquals(refSum / 100.0, stats.getMean(), 1E-10); 077 assertEquals(300, stats.getWindowSize()); 078 try { 079 stats.setWindowSize(-3); 080 fail("an exception should have been thrown"); 081 } catch (IllegalArgumentException iae) { 082 // expected 083 } catch (Exception e) { 084 fail("wrong exception caught: " + e.getMessage()); 085 } 086 assertEquals(300, stats.getWindowSize()); 087 stats.setWindowSize(50); 088 assertEquals(50, stats.getWindowSize()); 089 int refSum2 = refSum - (50 * 51) / 2; 090 assertEquals(refSum2 / 50.0, stats.getMean(), 1E-10); 091 } 092 093 public void testGetValues() { 094 DescriptiveStatistics stats = createDescriptiveStatistics(); 095 for (int i = 100; i > 0; --i) { 096 stats.addValue(i); 097 } 098 int refSum = (100 * 101) / 2; 099 assertEquals(refSum / 100.0, stats.getMean(), 1E-10); 100 double[] v = stats.getValues(); 101 for (int i = 0; i < v.length; ++i) { 102 assertEquals(100.0 - i, v[i], 1.0e-10); 103 } 104 double[] s = stats.getSortedValues(); 105 for (int i = 0; i < s.length; ++i) { 106 assertEquals(i + 1.0, s[i], 1.0e-10); 107 } 108 assertEquals(12.0, stats.getElement(88), 1.0e-10); 109 } 110 111 public void testToString() { 112 DescriptiveStatistics stats = createDescriptiveStatistics(); 113 stats.addValue(1); 114 stats.addValue(2); 115 stats.addValue(3); 116 Locale d = Locale.getDefault(); 117 Locale.setDefault(Locale.US); 118 assertEquals("DescriptiveStatistics:\n" + 119 "n: 3\n" + 120 "min: 1.0\n" + 121 "max: 3.0\n" + 122 "mean: 2.0\n" + 123 "std dev: 1.0\n" + 124 "median: 2.0\n" + 125 "skewness: 0.0\n" + 126 "kurtosis: NaN\n", stats.toString()); 127 Locale.setDefault(d); 128 } 129 130 public void testShuffledStatistics() { 131 // the purpose of this test is only to check the get/set methods 132 // we are aware shuffling statistics like this is really not 133 // something sensible to do in production ... 134 DescriptiveStatistics reference = createDescriptiveStatistics(); 135 DescriptiveStatistics shuffled = createDescriptiveStatistics(); 136 137 UnivariateStatistic tmp = shuffled.getGeometricMeanImpl(); 138 shuffled.setGeometricMeanImpl(shuffled.getMeanImpl()); 139 shuffled.setMeanImpl(shuffled.getKurtosisImpl()); 140 shuffled.setKurtosisImpl(shuffled.getSkewnessImpl()); 141 shuffled.setSkewnessImpl(shuffled.getVarianceImpl()); 142 shuffled.setVarianceImpl(shuffled.getMaxImpl()); 143 shuffled.setMaxImpl(shuffled.getMinImpl()); 144 shuffled.setMinImpl(shuffled.getSumImpl()); 145 shuffled.setSumImpl(shuffled.getSumsqImpl()); 146 shuffled.setSumsqImpl(tmp); 147 148 for (int i = 100; i > 0; --i) { 149 reference.addValue(i); 150 shuffled.addValue(i); 151 } 152 153 assertEquals(reference.getMean(), shuffled.getGeometricMean(), 1.0e-10); 154 assertEquals(reference.getKurtosis(), shuffled.getMean(), 1.0e-10); 155 assertEquals(reference.getSkewness(), shuffled.getKurtosis(), 1.0e-10); 156 assertEquals(reference.getVariance(), shuffled.getSkewness(), 1.0e-10); 157 assertEquals(reference.getMax(), shuffled.getVariance(), 1.0e-10); 158 assertEquals(reference.getMin(), shuffled.getMax(), 1.0e-10); 159 assertEquals(reference.getSum(), shuffled.getMin(), 1.0e-10); 160 assertEquals(reference.getSumsq(), shuffled.getSum(), 1.0e-10); 161 assertEquals(reference.getGeometricMean(), shuffled.getSumsq(), 1.0e-10); 162 163 } 164 165 public void testPercentileSetter() throws Exception { 166 DescriptiveStatistics stats = createDescriptiveStatistics(); 167 stats.addValue(1); 168 stats.addValue(2); 169 stats.addValue(3); 170 assertEquals(2, stats.getPercentile(50.0), 1E-10); 171 172 // Inject wrapped Percentile impl 173 stats.setPercentileImpl(new goodPercentile()); 174 assertEquals(2, stats.getPercentile(50.0), 1E-10); 175 176 // Try "new math" impl 177 stats.setPercentileImpl(new subPercentile()); 178 assertEquals(10.0, stats.getPercentile(10.0), 1E-10); 179 180 // Try to set bad impl 181 try { 182 stats.setPercentileImpl(new badPercentile()); 183 fail("Expecting IllegalArgumentException"); 184 } catch (IllegalArgumentException ex) { 185 // expected 186 } 187 } 188 189 public void test20090720() { 190 DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics(100); 191 for (int i = 0; i < 161; i++) { 192 descriptiveStatistics.addValue(1.2); 193 } 194 descriptiveStatistics.clear(); 195 descriptiveStatistics.addValue(1.2); 196 assertEquals(1, descriptiveStatistics.getN()); 197 } 198 199 public void testRemoval() { 200 201 final DescriptiveStatistics dstat = createDescriptiveStatistics(); 202 203 checkremoval(dstat, 1, 6.0, 0.0, Double.NaN); 204 checkremoval(dstat, 3, 5.0, 3.0, 4.5); 205 checkremoval(dstat, 6, 3.5, 2.5, 3.0); 206 checkremoval(dstat, 9, 3.5, 2.5, 3.0); 207 checkremoval(dstat, DescriptiveStatistics.INFINITE_WINDOW, 3.5, 2.5, 3.0); 208 209 } 210 211 public void checkremoval(DescriptiveStatistics dstat, int wsize, 212 double mean1, double mean2, double mean3) { 213 214 dstat.setWindowSize(wsize); 215 dstat.clear(); 216 217 for (int i = 1 ; i <= 6 ; ++i) { 218 dstat.addValue(i); 219 } 220 221 assertTrue(MathUtils.equals(mean1, dstat.getMean())); 222 dstat.replaceMostRecentValue(0); 223 assertTrue(MathUtils.equals(mean2, dstat.getMean())); 224 dstat.removeMostRecentValue(); 225 assertTrue(MathUtils.equals(mean3, dstat.getMean())); 226 227 } 228 229 // Test UnivariateStatistics impls for setter injection tests 230 231 /** 232 * A new way to compute the mean 233 */ 234 static class deepMean implements UnivariateStatistic { 235 236 public double evaluate(double[] values, int begin, int length) { 237 return 42; 238 } 239 240 public double evaluate(double[] values) { 241 return 42; 242 } 243 public UnivariateStatistic copy() { 244 return new deepMean(); 245 } 246 } 247 248 /** 249 * Test percentile implementation - wraps a Percentile 250 */ 251 static class goodPercentile implements UnivariateStatistic { 252 private Percentile percentile = new Percentile(); 253 public void setQuantile(double quantile) { 254 percentile.setQuantile(quantile); 255 } 256 public double evaluate(double[] values, int begin, int length) { 257 return percentile.evaluate(values, begin, length); 258 } 259 public double evaluate(double[] values) { 260 return percentile.evaluate(values); 261 } 262 public UnivariateStatistic copy() { 263 goodPercentile result = new goodPercentile(); 264 result.setQuantile(percentile.getQuantile()); 265 return result; 266 } 267 } 268 269 /** 270 * Test percentile subclass - another "new math" impl 271 * Always returns currently set quantile 272 */ 273 static class subPercentile extends Percentile { 274 @Override 275 public double evaluate(double[] values, int begin, int length) { 276 return getQuantile(); 277 } 278 @Override 279 public double evaluate(double[] values) { 280 return getQuantile(); 281 } 282 private static final long serialVersionUID = 8040701391045914979L; 283 @Override 284 public Percentile copy() { 285 subPercentile result = new subPercentile(); 286 return result; 287 } 288 } 289 290 /** 291 * "Bad" test percentile implementation - no setQuantile 292 */ 293 static class badPercentile implements UnivariateStatistic { 294 private Percentile percentile = new Percentile(); 295 public double evaluate(double[] values, int begin, int length) { 296 return percentile.evaluate(values, begin, length); 297 } 298 public double evaluate(double[] values) { 299 return percentile.evaluate(values); 300 } 301 public UnivariateStatistic copy() { 302 return new badPercentile(); 303 } 304 } 305 306 }