You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ps...@apache.org on 2004/10/10 22:40:52 UTC

cvs commit: jakarta-commons/math/src/test/org/apache/commons/math/stat/descriptive/moment VarianceTest.java

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 
  +     * {@link 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 {@link 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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org