diff --git a/src/java/org/apache/commons/math/stat/descriptive/moment/Variance.java b/src/java/org/apache/commons/math/stat/descriptive/moment/Variance.java index b9781b7a0..c8879ae94 100644 --- a/src/java/org/apache/commons/math/stat/descriptive/moment/Variance.java +++ b/src/java/org/apache/commons/math/stat/descriptive/moment/Variance.java @@ -20,7 +20,8 @@ import java.io.Serializable; 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: *
* variance = sum((x_i - mean)^2) / (n - 1) *
@@ -32,13 +33,19 @@ import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStati * as described in * Chan, T. F. andJ. G. Lewis 1979, Communications of the ACM, * vol. 22 no. 9, pp. 526-531.. -*
+ *
+ * The "population variance" ( sum((x_i - mean)^2) / n ) can also
+ * be computed using this statistic. The isBiasCorrected
+ * property determines whether the "population" or "sample" value is
+ * returned by the evaluate
and getResult
methods.
+ * To compute population variances, set this property to false.
+ *
* Note that this implementation is not synchronized. If
* multiple threads access an instance of this class concurrently, and at least
* one of the threads invokes the increment()
or
* clear()
method, it must be synchronized externally.
*
- * @version $Revision: 1.1 $ $Date: 2004/10/08 05:08:17 $
+ * @version $Revision: 1.2 $ $Date: 2004/10/10 20:40:52 $
*/
public class Variance extends AbstractStorelessUnivariateStatistic implements Serializable {
@@ -54,6 +61,13 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
* 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
+ * {@link Variance} for details on the formula.
+ */
+ private boolean isBiasCorrected = true;
/**
* Constructs a Variance.
@@ -64,6 +78,7 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
/**
* 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 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
incMoment = false;
this.moment = m2;
}
+
+ /**
+ * Constructs a Variance with the specified isBiasCorrected
+ * 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 isBiasCorrected
+ * 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 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
} 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 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
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 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
*
* See {@link Variance} for details on the computing algorithm. *
- * 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 isBiasCorrected
is true
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 isBiasCorrected
to false
before
+ * invoking this method.
*
* Returns 0 for a single-value (i.e. length = 1) sample. *
@@ -244,4 +300,18 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se 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; + } + } diff --git a/src/test/org/apache/commons/math/stat/descriptive/moment/VarianceTest.java b/src/test/org/apache/commons/math/stat/descriptive/moment/VarianceTest.java index 925d7f9d4..b76b328a7 100644 --- a/src/test/org/apache/commons/math/stat/descriptive/moment/VarianceTest.java +++ b/src/test/org/apache/commons/math/stat/descriptive/moment/VarianceTest.java @@ -24,7 +24,7 @@ import org.apache.commons.math.stat.descriptive.UnivariateStatistic; /** * Test cases for the {@link UnivariateStatistic} class. * - * @version $Revision: 1.1 $ $Date: 2004/10/08 05:08:20 $ + * @version $Revision: 1.2 $ $Date: 2004/10/10 20:40:52 $ */ public class VarianceTest extends StorelessUnivariateStatisticAbstractTest{ @@ -67,5 +67,33 @@ public class VarianceTest extends StorelessUnivariateStatisticAbstractTest{ 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; + } }