Improved javadoc, simplified implemenentation.

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@141341 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2004-06-27 19:37:51 +00:00
parent 0ad427869d
commit 6e21d23996
7 changed files with 135 additions and 138 deletions

View File

@ -20,57 +20,59 @@ import java.io.Serializable;
import org.apache.commons.math.stat.univariate.AbstractStorelessUnivariateStatistic; 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 * @version $Revision: 1.16 $ $Date: 2004/06/27 19:37:51 $
* <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: 1.15 $ $Date: 2004/06/23 16:26:15 $
*/ */
public class FirstMoment extends AbstractStorelessUnivariateStatistic implements Serializable{ public class FirstMoment extends AbstractStorelessUnivariateStatistic implements Serializable{
/** Serializable version identifier */ /** Serializable version identifier */
static final long serialVersionUID = -803343206421984070L; static final long serialVersionUID = -803343206421984070L;
/** count of values that have been added */ /** Count of values that have been added */
protected long n = 0; 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; protected double m1 = Double.NaN;
/** /**
* temporary internal state made available for * Deviation of most recently added value from previous first moment.
* higher order moments * Retained to prevent repeated computation in higher order moments.
*/ */
protected double dev = 0.0; protected double dev = Double.NaN;
/** /**
* temporary internal state made available for * Deviation of most recently added value from previous first moment,
* higher order moments * normalized by previous sample size. Retained to prevent repeated
* computation in higher order moments
*/ */
protected double v = 0.0; protected double nDev = Double.NaN;
/**
* temporary internal state made available for
* higher order moments
*/
protected double n0 = 0.0;
/** /**
* @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double) * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
*/ */
public void increment(final double d) { public void increment(final double d) {
if (n < 1) { if (n == 0) {
m1 = 0.0; m1 = 0.0;
} }
n++; n++;
double n0 = (double) n;
dev = d - m1; dev = d - m1;
n0 = (double) n; nDev = dev / n0;
v = dev / n0; m1 += nDev;
m1 += v;
} }
/** /**
@ -79,9 +81,8 @@ public class FirstMoment extends AbstractStorelessUnivariateStatistic implements
public void clear() { public void clear() {
m1 = Double.NaN; m1 = Double.NaN;
n = 0; n = 0;
dev = 0.0; dev = Double.NaN;
v = 0.0; nDev = Double.NaN;
n0 = 0.0;
} }
/** /**

View File

@ -18,11 +18,28 @@ package org.apache.commons.math.stat.univariate.moment;
import java.io.Serializable; import java.io.Serializable;
/** /**
* The FourthMoment is calculated using the following * Computes a statistic related to the Fourth Central Moment. Specifically,
* <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf"> * what is computed is the sum of
* recursive strategy * <p>
* </a>. Both incremental and evaluation strategies currently use this approach. * (x_i - xbar) ^ 4,
* @version $Revision: 1.17 $ $Date: 2004/06/23 16:26:15 $ * <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: 1.18 $ $Date: 2004/06/27 19:37:51 $
*/ */
public class FourthMoment extends ThirdMoment implements Serializable{ public class FourthMoment extends ThirdMoment implements Serializable{
@ -32,13 +49,6 @@ public class FourthMoment extends ThirdMoment implements Serializable{
/** fourth moment of values that have been added */ /** fourth moment of values that have been added */
protected double m4 = Double.NaN; 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) * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
*/ */
@ -50,16 +60,15 @@ public class FourthMoment extends ThirdMoment implements Serializable{
m1 = 0.0; m1 = 0.0;
} }
/* retain previous m3 */ double prevM3 = m3;
prevM3 = m3; double prevM2 = m2;
/* increment m1, m2 and m3 (and prevM2, _n0, _n1, _n2, _v, _v2) */
super.increment(d); super.increment(d);
n3 = (double) (n - 3); double n0 = (double) n;
m4 = m4 - (4.0 * v * prevM3) + (6.0 * v2 * prevM2) + m4 = m4 - 4.0 * nDev * prevM3 + 6.0 * nDevSq * prevM2 +
((n0 * n0) - 3 * n1) * (v2 * v2 * n1 * n0); ((n0 * n0) - 3 * (n0 -1)) * (nDevSq * nDevSq * (n0 - 1) * n0);
} }
/** /**
@ -75,8 +84,6 @@ public class FourthMoment extends ThirdMoment implements Serializable{
public void clear() { public void clear() {
super.clear(); super.clear();
m4 = Double.NaN; m4 = Double.NaN;
prevM3 = 0.0;
n3 = 0.0;
} }
} }

View File

@ -31,7 +31,7 @@ import org.apache.commons.math.stat.univariate.AbstractStorelessUnivariateStatis
* Note that this statistic is undefined for n < 4. <code>Double.Nan</code> is returned when * Note that this statistic is undefined for n < 4. <code>Double.Nan</code> is returned when
* there is not sufficient data to compute the statistic. * there is not sufficient data to compute the statistic.
* *
* @version $Revision: 1.22 $ $Date: 2004/06/23 16:26:14 $ * @version $Revision: 1.23 $ $Date: 2004/06/27 19:37:51 $
*/ */
public class Kurtosis extends AbstractStorelessUnivariateStatistic implements Serializable { public class Kurtosis extends AbstractStorelessUnivariateStatistic implements Serializable {
@ -86,14 +86,14 @@ public class Kurtosis extends AbstractStorelessUnivariateStatistic implements Se
double kurtosis = Double.NaN; double kurtosis = Double.NaN;
if (moment.getN() > 3) { if (moment.getN() > 3) {
double variance = moment.m2 / (double) (moment.n - 1); double variance = moment.m2 / (double) (moment.n - 1);
if (moment.n <= 3 || variance < 10E-20) { if (moment.n <= 3 || variance < 10E-20) {
kurtosis = 0.0; kurtosis = 0.0;
} else { } else {
double n = (double) moment.n;
kurtosis = kurtosis =
(moment.n0 * (moment.n0 + 1) * moment.m4 - (n * (n + 1) * moment.m4 -
3 * moment.m2 * moment.m2 * moment.n1) / 3 * moment.m2 * moment.m2 * (n - 1)) /
(moment.n1 * moment.n2 * moment.n3 * variance * variance); ((n - 1) * (n -2) * (n -3) * variance * variance);
} }
} }
return kurtosis; return kurtosis;

View File

@ -18,11 +18,20 @@ package org.apache.commons.math.stat.univariate.moment;
import java.io.Serializable; import java.io.Serializable;
/** /**
* The SecondMoment is calculated using the following * Computes a statistic related to the Second Central Moment. Specifically,
* <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf"> * what is computed is the sum of squared deviations from the sample mean.
* recursive strategy * <p>
* </a>. Both incremental and evaluation strategies currently use this approach. * The following recursive updating formula is used:
* @version $Revision: 1.16 $ $Date: 2004/06/23 16:26:15 $ * <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: 1.17 $ $Date: 2004/06/27 19:37:51 $
*/ */
public class SecondMoment extends FirstMoment implements Serializable { public class SecondMoment extends FirstMoment implements Serializable {
@ -32,9 +41,6 @@ public class SecondMoment extends FirstMoment implements Serializable {
/** second moment of values that have been added */ /** second moment of values that have been added */
protected double m2 = Double.NaN; 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) * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
*/ */
@ -42,15 +48,8 @@ public class SecondMoment extends FirstMoment implements Serializable {
if (n < 1) { if (n < 1) {
m1 = m2 = 0.0; m1 = m2 = 0.0;
} }
/* increment m1 and _n0, _dev, _v) */
super.increment(d); super.increment(d);
m2 += ((double) n - 1) * dev * nDev;
n1 = n0 - 1;
/* increment and return m2 */
m2 += n1 * dev * v;
} }
/** /**
@ -59,7 +58,6 @@ public class SecondMoment extends FirstMoment implements Serializable {
public void clear() { public void clear() {
super.clear(); super.clear();
m2 = Double.NaN; m2 = Double.NaN;
n1 = 0.0;
} }
/** /**

View File

@ -26,27 +26,27 @@ import org.apache.commons.math.stat.univariate.AbstractStorelessUnivariateStatis
* <p> * <p>
* skewness = [n / (n -1) (n - 2)] sum[(x_i - mean)^3] / std^3 * skewness = [n / (n -1) (n - 2)] sum[(x_i - mean)^3] / std^3
* <p> * <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: 1.21 $ $Date: 2004/06/23 16:26:14 $ * @version $Revision: 1.22 $ $Date: 2004/06/27 19:37:51 $
*/ */
public class Skewness extends AbstractStorelessUnivariateStatistic implements Serializable { public class Skewness extends AbstractStorelessUnivariateStatistic implements Serializable {
/** Serializable version identifier */ /** Serializable version identifier */
static final long serialVersionUID = 7101857578996691352L; static final long serialVersionUID = 7101857578996691352L;
/** */ /** Third moment on which this statistic is based */
protected ThirdMoment moment = null; 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 boolean incMoment = true;
/** */
protected double skewness = Double.NaN;
/** */
private long n = 0;
/** /**
* Constructs a Skewness * Constructs a Skewness
*/ */
@ -80,21 +80,18 @@ public class Skewness extends AbstractStorelessUnivariateStatistic implements Se
* @return the skewness of the available values. * @return the skewness of the available values.
*/ */
public double getResult() { public double getResult() {
if (n < moment.n) {
if (moment.n <= 0) {
skewness = Double.NaN;
}
double variance = if (moment.n < 3) {
(moment.n < 1) ? 0.0 : moment.m2 / (double) (moment.n - 1); return Double.NaN;
}
if (moment.n <= 2 || variance < 10E-20) { double variance = moment.m2 / (double) (moment.n - 1);
skewness = 0.0; double skewness = Double.NaN;
} else { if (variance < 10E-20) {
skewness = (moment.n0 * moment.m3) / skewness = 0.0;
(moment.n1 * moment.n2 * Math.sqrt(variance) * variance); } else {
} double n0 = (double) moment.getN();
n = moment.n; skewness = (n0 * moment.m3) /
((n0 - 1) * (n0 -2) * Math.sqrt(variance) * variance);
} }
return skewness; return skewness;
} }
@ -113,15 +110,8 @@ public class Skewness extends AbstractStorelessUnivariateStatistic implements Se
if (incMoment) { if (incMoment) {
moment.clear(); moment.clear();
} }
skewness = Double.NaN;
n = 0;
} }
/*UnvariateStatistic Approach */
/** */
Mean mean = new Mean();
/** /**
* Returns the Skewness of the values array. * Returns the Skewness of the values array.
* <p> * <p>
@ -142,7 +132,7 @@ public class Skewness extends AbstractStorelessUnivariateStatistic implements Se
double skew = Double.NaN; double skew = Double.NaN;
if (test(values, begin, length)) { if (test(values, begin, length)) {
Mean mean = new Mean();
if (length <= 2) { if (length <= 2) {
skew = 0.0; skew = 0.0;
} else { } else {

View File

@ -18,11 +18,21 @@ package org.apache.commons.math.stat.univariate.moment;
import java.io.Serializable; import java.io.Serializable;
/** /**
* The ThirdMoment (arithmentic mean) is calculated using the following * Computes a statistic related to the Third Central Moment. Specifically,
* <a href="http://www.spss.com/tech/stat/Algorithms/11.5/descriptives.pdf"> * what is computed is the sum of cubed deviations from the sample mean.
* recursive strategy * <p>
* </a>. Both incremental and evaluation strategies currently use this approach. * The following recursive updating formula is used:
* @version $Revision: 1.16 $ $Date: 2004/06/23 16:26:14 $ * <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: 1.17 $ $Date: 2004/06/27 19:37:51 $
*/ */
public class ThirdMoment extends SecondMoment implements Serializable { public class ThirdMoment extends SecondMoment implements Serializable {
@ -32,14 +42,13 @@ public class ThirdMoment extends SecondMoment implements Serializable {
/** third moment of values that have been added */ /** third moment of values that have been added */
protected double m3 = Double.NaN; protected double m3 = Double.NaN;
/** temporary internal state made availabel for higher order moments */ /**
protected double v2 = 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 n2 = 0.0;
/** temporary internal state made availabel for higher order moments */
protected double prevM2 = 0.0;
/** /**
* @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double) * @see org.apache.commons.math.stat.univariate.StorelessUnivariateStatistic#increment(double)
@ -49,17 +58,11 @@ public class ThirdMoment extends SecondMoment implements Serializable {
m3 = m2 = m1 = 0.0; m3 = m2 = m1 = 0.0;
} }
/* retain a reference to the last m2*/ double prevM2 = m2;
prevM2 = m2;
/* increment m1 and m2 (and _n0, _n1, _v) */
super.increment(d); super.increment(d);
nDevSq = nDev * nDev;
v2 = v * v; double n0 = (double) n;
n2 = (double) (n - 2); m3 = m3 - 3.0 * nDev * prevM2 + (n0 - 1) * (n0 - 2) * nDevSq * dev;
m3 = m3 - (3.0 * v * prevM2) + (n0 * n1 * n2 * v2 * v);
} }
/** /**
@ -75,9 +78,7 @@ public class ThirdMoment extends SecondMoment implements Serializable {
public void clear() { public void clear() {
super.clear(); super.clear();
m3 = Double.NaN; m3 = Double.NaN;
v2 = 0.0; nDevSq = Double.NaN;
n2 = 0.0;
prevM2 = 0.0;
} }
} }

View File

@ -33,7 +33,7 @@ import org.apache.commons.math.stat.univariate.AbstractStorelessUnivariateStatis
* Chan, T. F. andJ. G. Lewis 1979, <i>Communications of the ACM</i>, * Chan, T. F. andJ. G. Lewis 1979, <i>Communications of the ACM</i>,
* vol. 22 no. 9, pp. 526-531.</a>. * vol. 22 no. 9, pp. 526-531.</a>.
* *
* @version $Revision: 1.21 $ $Date: 2004/06/26 23:33:27 $ * @version $Revision: 1.22 $ $Date: 2004/06/27 19:37:51 $
*/ */
public class Variance extends AbstractStorelessUnivariateStatistic implements Serializable { public class Variance extends AbstractStorelessUnivariateStatistic implements Serializable {
@ -84,7 +84,7 @@ public class Variance extends AbstractStorelessUnivariateStatistic implements Se
} else if (moment.n == 1) { } else if (moment.n == 1) {
return 0d; return 0d;
} else { } else {
return moment.m2 / (moment.n0 - 1); return moment.m2 / ((double) moment.n - 1d);
} }
} }