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/06/27 21:37:52 UTC

cvs commit: jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment FirstMoment.java FourthMoment.java Kurtosis.java SecondMoment.java Skewness.java ThirdMoment.java Variance.java

psteitz     2004/06/27 12:37:52

  Modified:    math/src/java/org/apache/commons/math/stat/univariate/moment
                        FirstMoment.java FourthMoment.java Kurtosis.java
                        SecondMoment.java Skewness.java ThirdMoment.java
                        Variance.java
  Log:
  Improved javadoc, simplified implemenentation.
  
  Revision  Changes    Path
  1.16      +33 -32    jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/FirstMoment.java
  
  Index: FirstMoment.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/FirstMoment.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- FirstMoment.java	23 Jun 2004 16:26:15 -0000	1.15
  +++ FirstMoment.java	27 Jun 2004 19:37:51 -0000	1.16
  @@ -20,12 +20,21 @@
   import org.apache.commons.math.stat.univariate.AbstractStorelessUnivariateStatistic;
   
   /**
  - * FirstMoment.java
  + * Computes the first moment (arithmetic mean).  Uses the definitional formula:
  + * <p>
  + * mean = sum(x_i) / n
  + * <p>
  + * where <code>n</code> is the number of observations.
  + * <p>
  + * To limit numeric errors, the value of the statistic is computed using the
  + * following recursive updating algorithm:
  + * <p>
  + * <ol>
  + * <li>Initialize <code>m = </code> the first value</li>
  + * <li>For each additional value, update using <br>
  + *   <code>m = m + (new value - m) / (number of observations)</code></li>
  + * </ol>
    *
  - * The FirstMoment (arithmentic mean) is calculated using the following
  - * <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf">
  - * recursive strategy
  - * </a>. Both incremental and evaluation strategies currently use this approach.
    * @version $Revision$ $Date$
    */
   public class FirstMoment extends AbstractStorelessUnivariateStatistic implements Serializable{
  @@ -33,44 +42,37 @@
       /** Serializable version identifier */
       static final long serialVersionUID = -803343206421984070L; 
       
  -    /** count of values that have been added */
  +    /** Count of values that have been added */
       protected long n = 0;
   
  -    /** first moment of values that have been added */
  +    /** First moment of values that have been added */
       protected double m1 = Double.NaN;
  -
  -    /**
  -     * temporary internal state made available for
  -     * higher order moments
  -     */
  -    protected double dev = 0.0;
  -
  -    /**
  -     * temporary internal state made available for
  -     * higher order moments
  +    
  +    /** 
  +     * Deviation of most recently added value from previous first moment.
  +     * Retained to prevent repeated computation in higher order moments.
        */
  -    protected double v = 0.0;
  -
  +    protected double dev = Double.NaN;
  +    
       /**
  -     * temporary internal state made available for
  -     * higher order moments
  +     * Deviation of most recently added value from previous first moment,
  +     * normalized by previous sample size.  Retained to prevent repeated
  +     * computation in higher order moments
        */
  -    protected double n0 = 0.0;
  +    protected double nDev = Double.NaN;
   
       /**
        * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
        */
       public void increment(final double d) {
  -        if (n < 1) {
  +        if (n == 0) {
               m1 = 0.0;
           }
  -
           n++;
  +        double n0 = (double) n;
           dev = d - m1;
  -        n0 = (double) n;
  -        v = dev / n0;
  -
  -        m1 += v;
  +        nDev = dev / n0;
  +        m1 += nDev;
       }
   
       /**
  @@ -79,9 +81,8 @@
       public void clear() {
           m1 = Double.NaN;
           n = 0;
  -        dev = 0.0;
  -        v = 0.0;
  -        n0 = 0.0;
  +        dev = Double.NaN;
  +        nDev = Double.NaN;
       }
   
       /**
  
  
  
  1.18      +29 -22    jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/FourthMoment.java
  
  Index: FourthMoment.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/FourthMoment.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- FourthMoment.java	23 Jun 2004 16:26:15 -0000	1.17
  +++ FourthMoment.java	27 Jun 2004 19:37:51 -0000	1.18
  @@ -18,10 +18,27 @@
   import java.io.Serializable;
   
   /**
  - * The FourthMoment is calculated using the following
  - * <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf">
  - * recursive strategy
  - * </a>. Both incremental and evaluation strategies currently use this approach.
  + * Computes a statistic related to the Fourth Central Moment.  Specifically,
  + * what is computed is the sum of 
  + * <p>
  + * (x_i - xbar) ^ 4,
  + * <p>
  + * where the x_i are the 
  + * sample observations and xbar is the sample mean.
  + * <p>
  + * The following recursive updating formula is used:
  + * <p>
  + * Let <ul>
  + * <li> dev = (current obs - previous mean) </li>
  + * <li> m2 = previous value of {@link SecondMoment} </li>
  + * <li> m2 = previous value of {@link ThirdMoment} </li>
  + * <li> n = number of observations (including current obs) </li>
  + * </ul>
  + * Then
  + * <p>
  + * new value = old value - 4 * (dev/n) * m3 + 6 * (dev/n)^2 * m2 + <br>
  + * [n^2 - 3 * (n-1)] * dev^4 * (n-1) / n^3
  + * 
    * @version $Revision$ $Date$
    */
   public class FourthMoment extends ThirdMoment implements Serializable{
  @@ -32,13 +49,6 @@
       /** fourth moment of values that have been added */
       protected double m4 = Double.NaN;
   
  -    /** temporary internal state made available for higher order moments */
  -    protected double prevM3 = 0.0;
  -
  -    /** temporary internal state made available for higher order moments */
  -    protected double n3 = 0.0;
  -
  -
       /**
        * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
        */
  @@ -50,16 +60,15 @@
               m1 = 0.0;
           }
   
  -        /* retain previous m3 */
  -        prevM3 = m3;
  -
  -        /* increment m1, m2 and m3 (and prevM2, _n0, _n1, _n2, _v, _v2) */
  +        double prevM3 = m3;
  +        double prevM2 = m2;
  +        
           super.increment(d);
  +        
  +        double n0 = (double) n;
   
  -        n3 = (double) (n - 3);
  -
  -        m4 = m4 - (4.0 * v * prevM3) + (6.0 * v2 * prevM2) +
  -            ((n0 * n0) - 3 * n1) * (v2 * v2 * n1 * n0);
  +        m4 = m4 - 4.0 * nDev * prevM3 + 6.0 * nDevSq * prevM2 +
  +            ((n0 * n0) - 3 * (n0 -1)) * (nDevSq * nDevSq * (n0 - 1) * n0);
       }
   
       /**
  @@ -75,8 +84,6 @@
       public void clear() {
           super.clear();
           m4 = Double.NaN;
  -        prevM3 = 0.0;
  -        n3 = 0.0;
       }
   
   }
  
  
  
  1.23      +5 -5      jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/Kurtosis.java
  
  Index: Kurtosis.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/Kurtosis.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Kurtosis.java	23 Jun 2004 16:26:14 -0000	1.22
  +++ Kurtosis.java	27 Jun 2004 19:37:51 -0000	1.23
  @@ -86,14 +86,14 @@
           double kurtosis = Double.NaN;
           if (moment.getN() > 3) {
               double variance = moment.m2 / (double) (moment.n - 1);
  -                
                   if (moment.n <= 3 || variance < 10E-20) {
                       kurtosis = 0.0;
                   } else {
  +                    double n = (double) moment.n;
                       kurtosis =
  -                        (moment.n0 * (moment.n0 + 1) * moment.m4 -
  -                                3 * moment.m2 * moment.m2 * moment.n1) /
  -                                (moment.n1 * moment.n2 * moment.n3 * variance * variance);
  +                        (n * (n + 1) * moment.m4 -
  +                                3 * moment.m2 * moment.m2 * (n - 1)) /
  +                                ((n - 1) * (n -2) * (n -3) * variance * variance);
                   }
           }
           return kurtosis;
  
  
  
  1.17      +15 -17    jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/SecondMoment.java
  
  Index: SecondMoment.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/SecondMoment.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- SecondMoment.java	23 Jun 2004 16:26:15 -0000	1.16
  +++ SecondMoment.java	27 Jun 2004 19:37:51 -0000	1.17
  @@ -18,10 +18,19 @@
   import java.io.Serializable;
   
   /**
  - * The SecondMoment is calculated using the following
  - * <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf">
  - * recursive strategy
  - * </a>. Both incremental and evaluation strategies currently use this approach.
  + * Computes a statistic related to the Second Central Moment.  Specifically,
  + * what is computed is the sum of squared deviations from the sample mean.
  + * <p>
  + * The following recursive updating formula is used:
  + * <p>
  + * Let <ul>
  + * <li> dev = (current obs - previous mean) </li>
  + * <li> n = number of observations (including current obs) </li>
  + * </ul>
  + * Then
  + * <p>
  + * new value = old value + dev^2 * (n -1) / n.
  + * 
    * @version $Revision$ $Date$
    */
   public class SecondMoment extends FirstMoment implements Serializable {
  @@ -32,9 +41,6 @@
       /** second moment of values that have been added */
       protected double m2 = Double.NaN;
   
  -    /** temporary internal state made availabel for higher order moments */
  -    protected double n1 = 0.0;
  -
       /**
        * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
        */
  @@ -42,15 +48,8 @@
           if (n < 1) {
               m1 = m2 = 0.0;
           }
  -
  -        /* increment m1 and _n0, _dev,  _v) */
           super.increment(d);
  -
  -        n1 = n0 - 1;
  -
  -        /* increment and return m2 */
  -        m2 += n1 * dev * v;
  -
  +        m2 += ((double) n - 1) * dev * nDev;
       }
   
       /**
  @@ -59,7 +58,6 @@
       public void clear() {
           super.clear();
           m2 = Double.NaN;
  -        n1 = 0.0;
       }
   
       /**
  
  
  
  1.22      +23 -33    jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/Skewness.java
  
  Index: Skewness.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/Skewness.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- Skewness.java	23 Jun 2004 16:26:14 -0000	1.21
  +++ Skewness.java	27 Jun 2004 19:37:51 -0000	1.22
  @@ -26,7 +26,8 @@
    *  <p>
    *  skewness = [n / (n -1) (n - 2)] sum[(x_i - mean)^3] / std^3
    *  <p>
  - *  where n is the number of values, mean is the {@link Mean} and std is the {@link StandardDeviation}
  + *  where n is the number of values, mean is the {@link Mean} and std is the 
  + * {@link StandardDeviation}
    *
    * @version $Revision$ $Date$
    */
  @@ -35,18 +36,17 @@
       /** Serializable version identifier */
       static final long serialVersionUID = 7101857578996691352L;    
       
  -    /** */
  +    /** Third moment on which this statistic is based */
       protected ThirdMoment moment = null;
   
  -    /** */
  +     /** 
  +     * Determines whether or not this statistic can be incremented or cleared.
  +     * <p>
  +     * Statistics based on (constructed from) external moments cannot
  +     * be incremented or cleared.
  +    */
       protected boolean incMoment = true;
   
  -    /** */
  -    protected double skewness = Double.NaN;
  -
  -    /** */
  -    private long n = 0;
  -
       /**
        * Constructs a Skewness
        */
  @@ -80,21 +80,18 @@
        * @return the skewness of the available values.
        */
       public double getResult() {
  -        if (n < moment.n) {
  -            if (moment.n <= 0) {
  -                skewness = Double.NaN;
  -            }
  -
  -            double variance =
  -                (moment.n < 1) ? 0.0 : moment.m2 / (double) (moment.n - 1);
  -
  -            if (moment.n <= 2 || variance < 10E-20) {
  -                skewness = 0.0;
  -            } else {
  -                skewness = (moment.n0 * moment.m3) /
  -                    (moment.n1 * moment.n2 * Math.sqrt(variance) * variance);
  -            }
  -            n = moment.n;
  +        
  +        if (moment.n < 3) {
  +            return Double.NaN;
  +        }
  +        double variance = moment.m2 / (double) (moment.n - 1);
  +        double skewness = Double.NaN;
  +        if (variance < 10E-20) {
  +            skewness = 0.0;
  +        } else {
  +            double n0 = (double) moment.getN();
  +            skewness = (n0 * moment.m3) /
  +            ((n0 - 1) * (n0 -2) * Math.sqrt(variance) * variance);
           }
           return skewness;
       }
  @@ -113,15 +110,8 @@
           if (incMoment) {
               moment.clear();
           }
  -        skewness = Double.NaN;
  -        n = 0;
       }
   
  -    /*UnvariateStatistic Approach */
  -
  -    /** */
  -    Mean mean = new Mean();
  -
       /**
        * Returns the Skewness of the values array.
        * <p>
  @@ -142,7 +132,7 @@
           double skew = Double.NaN;
   
           if (test(values, begin, length)) {
  -
  +            Mean mean = new Mean();
               if (length <= 2) {
                   skew = 0.0;
               } else {
  
  
  
  1.17      +28 -27    jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/ThirdMoment.java
  
  Index: ThirdMoment.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/ThirdMoment.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- ThirdMoment.java	23 Jun 2004 16:26:14 -0000	1.16
  +++ ThirdMoment.java	27 Jun 2004 19:37:51 -0000	1.17
  @@ -18,10 +18,20 @@
   import java.io.Serializable;
   
   /**
  - * The ThirdMoment (arithmentic mean) is calculated using the following
  - * <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf">
  - * recursive strategy
  - * </a>. Both incremental and evaluation strategies currently use this approach.
  + * Computes a statistic related to the Third Central Moment.  Specifically,
  + * what is computed is the sum of cubed deviations from the sample mean.
  + * <p>
  + * The following recursive updating formula is used:
  + * <p>
  + * Let <ul>
  + * <li> dev = (current obs - previous mean) </li>
  + * <li> m2 = previous value of {@link SecondMoment} </li>
  + * <li> n = number of observations (including current obs) </li>
  + * </ul>
  + * Then
  + * <p>
  + * new value = old value - 3 * (dev/n) * m2 + (n-1) * (n -2) * (dev^3/n^2)
  + * 
    * @version $Revision$ $Date$
    */
   public class ThirdMoment extends SecondMoment implements Serializable {
  @@ -32,14 +42,13 @@
       /** third moment of values that have been added */
       protected double m3 = Double.NaN;
   
  -    /** temporary internal state made availabel for higher order moments */
  -    protected double v2 = 0.0;
  -
  -    /** temporary internal state made availabel for higher order moments */
  -    protected double n2 = 0.0;
  +     /**
  +     * Square of deviation of most recently added value from previous first 
  +     * moment, normalized by previous sample size.  Retained to prevent 
  +     * repeated computation in higher order moments.  nDevSq = nDev * nDev.
  +     */
  +    protected double nDevSq = Double.NaN;
   
  -    /** temporary internal state made availabel for higher order moments */
  -    protected double prevM2 = 0.0;
   
       /**
        * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
  @@ -47,19 +56,13 @@
       public void increment(final double d) {
           if (n < 1) {
               m3 = m2 = m1 = 0.0;
  -        }
  -
  -        /* retain a reference to the last m2*/
  -        prevM2 = m2;
  -
  -        /* increment m1 and m2 (and _n0, _n1, _v) */
  +        }  
  +       
  +        double prevM2 = m2;
           super.increment(d);
  -
  -        v2 = v * v;
  -        n2 = (double) (n - 2);
  -
  -        m3 = m3 - (3.0 * v * prevM2) + (n0 * n1 * n2 * v2 * v);
  -
  +        nDevSq = nDev * nDev;
  +        double n0 = (double) n;
  +        m3 = m3 - 3.0 * nDev * prevM2 + (n0 - 1) * (n0 - 2) * nDevSq * dev;
       }
   
       /**
  @@ -75,9 +78,7 @@
       public void clear() {
           super.clear();
           m3 = Double.NaN;
  -        v2 = 0.0;
  -        n2 = 0.0;
  -        prevM2 = 0.0;
  +        nDevSq = Double.NaN;
       }
   
   }
  
  
  
  1.22      +2 -2      jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/Variance.java
  
  Index: Variance.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/univariate/moment/Variance.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- Variance.java	26 Jun 2004 23:33:27 -0000	1.21
  +++ Variance.java	27 Jun 2004 19:37:51 -0000	1.22
  @@ -84,7 +84,7 @@
               } else if (moment.n == 1) {
                   return 0d;
               } else {
  -                return moment.m2 / (moment.n0 - 1);
  +                return moment.m2 / ((double) moment.n - 1d);
               }
       }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org