Patch adds getSkewness and getKurtosis to Univariate and an implimentation

in UnivariateImpl. It also adds test for NaN and 0.0 to UnivariateImplTest

PR: Issue 20250
Obtained from: Bugzilla
Submitted by: Mark Diggory
Reviewed by: Tim O'Brien


git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@140866 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim O'Brien 2003-05-29 19:49:18 +00:00
parent 8a13741f2d
commit be5a9fb219
3 changed files with 138 additions and 29 deletions

View File

@ -73,7 +73,7 @@
* @author Phil Steitz * @author Phil Steitz
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a> * @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
* @author Mark Diggory * @author Mark Diggory
* @version $Revision: 1.7 $ $Date: 2003/05/26 17:40:20 $ * @version $Revision: 1.8 $ $Date: 2003/05/29 19:49:18 $
* *
*/ */
public interface Univariate { public interface Univariate {
@ -132,6 +132,26 @@ public interface Univariate {
*/ */
abstract double getStandardDeviation(); abstract double getStandardDeviation();
/**
* Returns the skewness of a given distribution. Skewness is a
* measure of the assymetry of a given distribution. <p>
* Double.NaN is returned for an empty set of values and 0.0 is
* returned for a value set &lt;=2.
*
* @return Value of property skewness.
*/
abstract double getSkewness();
/**
* Returns the Kurtosis of the available values. Kurtosis is a
* measure of the "peakedness" of a distribution <p>
* Double.NaN is returned for an empty set of values and 0.0 is
* returned for a value set &lt;=3.
*
* @return Value of property kurtosis.
*/
abstract double getKurtosis();
/** /**
* Returns the maximum of the available values <p> * Returns the maximum of the available values <p>
* Double.NaN is returned in no values have been added * Double.NaN is returned in no values have been added

View File

@ -67,7 +67,7 @@ import java.io.Serializable;
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a> * @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
* @author Mark Diggory * @author Mark Diggory
* @author Brent Worden * @author Brent Worden
* @version $Revision: 1.8 $ $Date: 2003/05/26 17:40:20 $ * @version $Revision: 1.9 $ $Date: 2003/05/29 19:49:18 $
* *
*/ */
public class UnivariateImpl implements Univariate, Serializable { public class UnivariateImpl implements Univariate, Serializable {
@ -86,6 +86,12 @@ public class UnivariateImpl implements Univariate, Serializable {
/** running sum of squares that have been added */ /** running sum of squares that have been added */
private double sumsq = 0.0; private double sumsq = 0.0;
/** running sum of 3rd powers that have been added */
private double sumCube = 0.0;
/** running sum of 4th powers that have been added */
private double sumQuad = 0.0;
/** count of values that have been added */ /** count of values that have been added */
private int n = 0; private int n = 0;
@ -162,6 +168,44 @@ public class UnivariateImpl implements Univariate, Serializable {
} }
} }
/**
* Returns the skewness of the values that have been added as described by
* <a href=http://mathworld.wolfram.com/k-Statistic.html>Equation (6) for k-Statistics</a>.
*
* @return The skew of a set of values. Double.NaN is returned for
* an empty set of values and 0.0 is returned for a &lt;= 2 value set.
*/
public double getSkewness() {
if( n < 1) return Double.NaN;
if( n <= 2 ) return 0.0;
return ( 2*Math.pow(sum,3) - 3*sum*sumsq + ((double)n)*((double)n)*sumCube ) /
( ((double)n)*(((double)n)-1)*(((double)n)-2));
}
/**
* Returns the kurtosis of the values that have been added as described by
* <a href=http://mathworld.wolfram.com/k-Statistic.html>Equation (7) for k-Statistics</a>.
*
* @return The kurtosis of a set of values. Double.NaN is returned for
* an empty set of values and 0.0 is returned for a &lt;= 3 value set.
*/
public double getKurtosis() {
if( n < 1) return Double.NaN;
if( n <= 3 ) return 0.0;
double x1 = -6*Math.pow(sum,4);
double x2 = 12*((double)n)*Math.pow(sum,2)*sumsq;
double x3 = -3*((double)n)*(((double)n)-1)*Math.pow(sumsq,2);
double x4 = -4*((double)n)*(((double)n)+1)*sum*sumCube;
double x5 = Math.pow(((double)n),2)*(((double)n)+1)*sumQuad;
return (x1 + x2 + x3 + x4 + x5) /
(((double)n)*(((double)n)-1)*(((double)n)-2)*(((double)n)-3));
}
private void insertValue(double v) { private void insertValue(double v) {
// The default value of product is NaN, if you // The default value of product is NaN, if you
@ -176,14 +220,15 @@ public class UnivariateImpl implements Univariate, Serializable {
} }
if( windowSize != Univariate.INFINITE_WINDOW ) { if( windowSize != Univariate.INFINITE_WINDOW ) {
if( windowSize == n ) { if( windowSize == n ) {
double discarded = doubleArray.addElementRolling( v ); double discarded = doubleArray.addElementRolling( v );
// Remove the influence of the discarded // Remove the influence of the discarded
sum -= discarded; sum -= discarded;
sumsq -= discarded * discarded; sumsq -= discarded * discarded;
sumCube -= Math.pow(discarded,3);
sumQuad -= Math.pow(discarded,4);
if(discarded == min) { if(discarded == min) {
min = doubleArray.getMin(); min = doubleArray.getMin();
} else { } else {
@ -192,9 +237,6 @@ public class UnivariateImpl implements Univariate, Serializable {
} }
} }
sum += v;
sumsq += v*v;
if(product != 0.0){ if(product != 0.0){
// can safely remove discarded value // can safely remove discarded value
product *= v/discarded; product *= v/discarded;
@ -203,7 +245,7 @@ public class UnivariateImpl implements Univariate, Serializable {
product = 1.0; product = 1.0;
double[] elements = doubleArray.getElements(); double[] elements = doubleArray.getElements();
for( int i = 0; i < elements.length; i++ ) { for( int i = 0; i < elements.length; i++ ) {
product *= elements[i]; product *= elements[i];
} }
} // else product = 0 and will still be 0 after discard } // else product = 0 and will still be 0 after discard
@ -212,8 +254,6 @@ public class UnivariateImpl implements Univariate, Serializable {
n += 1.0; n += 1.0;
if (v < min) min = v; if (v < min) min = v;
if (v > max) max = v; if (v > max) max = v;
sum += v;
sumsq += v*v;
product *= v; product *= v;
} }
} else { } else {
@ -223,10 +263,13 @@ public class UnivariateImpl implements Univariate, Serializable {
n += 1.0; n += 1.0;
if (v < min) min = v; if (v < min) min = v;
if (v > max) max = v; if (v > max) max = v;
sum += v;
sumsq += v*v;
product *= v; product *= v;
} }
sum += v;
sumsq += v*v;
sumCube += Math.pow(v,3);
sumQuad += Math.pow(v,4);
} }
/** Getter for property max. /** Getter for property max.
@ -272,6 +315,20 @@ public class UnivariateImpl implements Univariate, Serializable {
return sumsq; return sumsq;
} }
/** Getter for property sumCube.
* @return Value of property sumCube.
*/
public double getSumCube() {
return sumCube;
}
/** Getter for property sumQuad.
* @return Value of property sumQuad.
*/
public double getSumQuad() {
return sumQuad;
}
/** /**
* Generates a text report displaying * Generates a text report displaying
* univariate statistics from values that * univariate statistics from values that
@ -286,13 +343,14 @@ public class UnivariateImpl implements Univariate, Serializable {
outBuffer.append("max: " + max + "\n"); outBuffer.append("max: " + max + "\n");
outBuffer.append("mean: " + getMean() + "\n"); outBuffer.append("mean: " + getMean() + "\n");
outBuffer.append("std dev: " + getStandardDeviation() + "\n"); outBuffer.append("std dev: " + getStandardDeviation() + "\n");
outBuffer.append("skewness: " + getSkewness() + "\n");
outBuffer.append("kurtosis: " + getKurtosis() + "\n");
return outBuffer.toString(); return outBuffer.toString();
} }
/** Resets all sums to 0, resets min and max */ /** Resets all sums to 0, resets min and max */
public void clear() { public void clear() {
this.sum = 0.0; this.sum = this.sumsq = this.sumCube = this.sumQuad = 0.0;
this.sumsq = 0.0;
this.n = 0; this.n = 0;
this.min = Double.MAX_VALUE; this.min = Double.MAX_VALUE;
this.max = Double.MIN_VALUE; this.max = Double.MIN_VALUE;

View File

@ -62,7 +62,7 @@ import junit.framework.TestSuite;
* *
* @author Phil Steitz * @author Phil Steitz
* @author Tim Obrien * @author Tim Obrien
* @version $Revision: 1.3 $ $Date: 2003/05/23 17:33:18 $ * @version $Revision: 1.4 $ $Date: 2003/05/29 19:49:18 $
*/ */
public final class UnivariateImplTest extends TestCase { public final class UnivariateImplTest extends TestCase {
@ -117,19 +117,54 @@ public final class UnivariateImplTest extends TestCase {
UnivariateImpl u = new UnivariateImpl(); UnivariateImpl u = new UnivariateImpl();
assertTrue("Mean of n = 0 set should be NaN", assertTrue("Mean of n = 0 set should be NaN",
Double.isNaN( u.getMean() ) ); Double.isNaN( u.getMean() ) );
assertTrue("Standard Deviation of n = 0 set should be NaN", assertTrue("Standard Deviation of n = 0 set should be NaN",
Double.isNaN( u.getStandardDeviation() ) ); Double.isNaN( u.getStandardDeviation() ) );
assertTrue("Variance of n = 0 set should be NaN", assertTrue("Variance of n = 0 set should be NaN",
Double.isNaN(u.getVariance() ) ); Double.isNaN(u.getVariance() ) );
assertTrue("skew of n = 0 set should be NaN",
Double.isNaN(u.getSkewness() ) );
assertTrue("kurtosis of n = 0 set should be NaN",
Double.isNaN(u.getKurtosis() ) );
u.addValue(one); /* n=1 */
u.addValue(one);
assertTrue("mean should be one (n = 1)",
u.getMean() == one);
assertTrue("geometric should be one (n = 1)",
u.getGeometricMean() == one);
assertTrue("Std should be zero (n = 1)",
u.getStandardDeviation() == 0.0);
assertTrue("variance should be zero (n = 1)",
u.getVariance() == 0.0);
assertTrue("skew should be zero (n = 1)",
u.getSkewness() == 0.0);
assertTrue("kurtosis should be zero (n = 1)",
u.getKurtosis() == 0.0);
/* n=2 */
u.addValue(twoF);
assertTrue("Std should not be zero (n = 2)",
u.getStandardDeviation() != 0.0);
assertTrue("variance should not be zero (n = 2)",
u.getVariance() != 0.0);
assertTrue("skew should not be zero (n = 2)",
u.getSkewness() == 0.0);
assertTrue("kurtosis should be zero (n = 2)",
u.getKurtosis() == 0.0);
assertTrue( "Mean of n = 1 set should be value of single item n1", /* n=3 */
u.getMean() == one); u.addValue(twoL);
assertTrue( "Mean of n = 1 set should be zero", assertTrue("skew should not be zero (n = 3)",
u.getStandardDeviation() == 0); u.getSkewness() != 0.0);
assertTrue( "Variance of n = 1 set should be zero", assertTrue("kurtosis should be zero (n = 3)",
u.getVariance() == 0); u.getKurtosis() == 0.0);
/* n=4 */
u.addValue(three);
assertTrue("kurtosis should not be zero (n = 4)",
u.getKurtosis() != 0.0);
} }
public void testProductAndGeometricMean() throws Exception { public void testProductAndGeometricMean() throws Exception {
@ -199,9 +234,5 @@ public final class UnivariateImplTest extends TestCase {
//FiXME: test all other NaN contract specs //FiXME: test all other NaN contract specs
} }
}
}