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:
parent
8a13741f2d
commit
be5a9fb219
|
@ -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 <=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 <=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
|
||||||
|
|
|
@ -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 <= 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 <= 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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue