psteitz 2004/10/10 13:40:52 Modified: math/src/java/org/apache/commons/math/stat/descriptive/moment Variance.java math/src/test/org/apache/commons/math/stat/descriptive/moment VarianceTest.java Log: Added support for population variance computation. Revision Changes Path 1.2 +80 -10 jakarta-commons/math/src/java/org/apache/commons/math/stat/descriptive/moment/Variance.java Index: Variance.java =================================================================== RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/descriptive/moment/Variance.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Variance.java 8 Oct 2004 05:08:17 -0000 1.1 +++ Variance.java 10 Oct 2004 20:40:52 -0000 1.2 @@ -20,7 +20,8 @@ import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic; /** - * Computes the (unbiased) sample variance. Uses the definitional formula: + * Computes the variance of the available values. By default, the unbiased + * "sample variance" definitional formula is used: * <p> * variance = sum((x_i - mean)^2) / (n - 1) * <p> @@ -32,7 +33,13 @@ * as described in <a href="http://doi.acm.org/10.1145/359146.359152"> * Chan, T. F. andJ. G. Lewis 1979, <i>Communications of the ACM</i>, * vol. 22 no. 9, pp. 526-531.</a>. -* <p> + * <p> + * The "population variance" ( sum((x_i - mean)^2) / n ) can also + * be computed using this statistic. The <code>isBiasCorrected</code> + * property determines whether the "population" or "sample" value is + * returned by the <code>evaluate</code> and <code>getResult</code> methods. + * To compute population variances, set this property to <code>false.</code> + * * <strong>Note that this implementation is not synchronized.</strong> If * multiple threads access an instance of this class concurrently, and at least * one of the threads invokes the <code>increment()</code> or @@ -54,6 +61,13 @@ * constructed with an external SecondMoment as a parameter. */ protected boolean incMoment = true; + + /** + * Determines whether or not bias correction is applied when computing the + * value of the statisic. True means that bias is corrected. See + * [EMAIL PROTECTED] Variance} for details on the formula. + */ + private boolean isBiasCorrected = true; /** * Constructs a Variance. @@ -64,6 +78,7 @@ /** * Constructs a Variance based on an external second moment. + * * @param m2 the SecondMoment (Thrid or Fourth moments work * here as well.) */ @@ -71,6 +86,36 @@ incMoment = false; this.moment = m2; } + + /** + * Constructs a Variance with the specified <code>isBiasCorrected</code> + * property + * + * @param isBiasCorrected setting for bias correction - true means + * bias will be corrected and is equivalent to using the argumentless + * constructor + */ + public Variance(boolean isBiasCorrected) { + moment = new SecondMoment(); + this.isBiasCorrected = isBiasCorrected; + } + + /** + * Constructs a Variance with the specified <code>isBiasCorrected</code> + * property and the supplied external second moment. + * + * @param isBiasCorrected setting for bias correction - true means + * bias will be corrected and is equivalent to using the argumentless + * constructor + * @param m2 the SecondMoment (Thrid or Fourth moments work + * here as well.) + */ + public Variance(boolean isBiasCorrected, SecondMoment m2) { + incMoment = false; + this.moment = m2; + this.isBiasCorrected = isBiasCorrected; + } + /** * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#increment(double) */ @@ -89,7 +134,11 @@ } else if (moment.n == 1) { return 0d; } else { - return moment.m2 / ((double) moment.n - 1d); + if (isBiasCorrected) { + return moment.m2 / ((double) moment.n - 1d); + } else { + return moment.m2 / ((double) moment.n); + } } } @@ -210,8 +259,13 @@ accum += Math.pow((values[i] - mean), 2.0); accum2 += (values[i] - mean); } - var = (accum - (Math.pow(accum2, 2) / ((double) length))) / - (double) (length - 1); + if (isBiasCorrected) { + var = (accum - (Math.pow(accum2, 2) / ((double) length))) / + (double) (length - 1); + } else { + var = (accum - (Math.pow(accum2, 2) / ((double) length))) / + (double) length; + } } } return var; @@ -224,10 +278,12 @@ * <p> * See [EMAIL PROTECTED] Variance} for details on the computing algorithm. * <p> - * The formula used assumes that the supplied mean value is the arithmetic - * mean of the sample data, not a known population parameter. This method - * is supplied only to save computation when the mean has already been - * computed. + * If <code>isBiasCorrected</code> is <code>true</code> the formula used + * assumes that the supplied mean value is the arithmetic mean of the + * sample data, not a known population parameter. If the mean is a known + * population parameter, or if the "population" version of the variance is + * desired, set <code>isBiasCorrected</code> to <code>false</code> before + * invoking this method. * <p> * Returns 0 for a single-value (i.e. length = 1) sample. * <p> @@ -242,6 +298,20 @@ */ public double evaluate(final double[] values, final double mean) { return evaluate(values, mean, 0, values.length); + } + + /** + * @return Returns the isBiasCorrected. + */ + public boolean isBiasCorrected() { + return isBiasCorrected; + } + + /** + * @param isBiasCorrected The isBiasCorrected to set. + */ + public void setBiasCorrected(boolean isBiasCorrected) { + this.isBiasCorrected = isBiasCorrected; } } 1.2 +29 -1 jakarta-commons/math/src/test/org/apache/commons/math/stat/descriptive/moment/VarianceTest.java Index: VarianceTest.java =================================================================== RCS file: /home/cvs/jakarta-commons/math/src/test/org/apache/commons/math/stat/descriptive/moment/VarianceTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- VarianceTest.java 8 Oct 2004 05:08:20 -0000 1.1 +++ VarianceTest.java 10 Oct 2004 20:40:52 -0000 1.2 @@ -67,5 +67,33 @@ std.increment(1d); assertEquals(0d, std.getResult(), 0); } + + /** + * Test population version of variance + */ + public void testPopulation() { + double[] values = {-1.0d, 3.1d, 4.0d, -2.1d, 22d, 11.7d, 3d, 14d}; + SecondMoment m = new SecondMoment(); + m.evaluate(values); // side effect is to add values + Variance v1 = new Variance(); + v1.setBiasCorrected(false); + assertEquals(populationVariance(values), v1.evaluate(values), 1E-14); + v1.incrementAll(values); + assertEquals(populationVariance(values), v1.getResult(), 1E-14); + v1 = new Variance(false, m); + assertEquals(populationVariance(values), v1.getResult(), 1E-14); + } + + /** + * Definitional formula for population variance + */ + protected double populationVariance(double[] v) { + double mean = new Mean().evaluate(v); + double sum = 0; + for (int i = 0; i < v.length; i++) { + sum += (v[i] - mean) * (v[i] - mean); + } + return sum / (double) v.length; + } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]