Added Product and Mean to Univariate and all implementations, this patch
contains contributions from Mark Diggory. * This patch introduces Product and GeometricMean into the Univariate implementation. * Discarding the contribution of a discarded element in a rolling UnivariateImpl requires that the product be calculated explicitly each time a value is discarded. This is necessary because not all values will have non-zero values. * Errors in rolling logic for ListUimpl, and UnivariateImpl were corrected, and more test cases were added to the JUnit tests for the Univariate implementations. More rigorous test cases are needed for the entire suite of Univariate implementations git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@140851 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a3e8ae46e0
commit
8ed6e84dc6
|
@ -57,6 +57,7 @@ package org.apache.commons.math;
|
|||
* Provides univariate measures for an array of doubles.
|
||||
*
|
||||
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
|
||||
* @author Mark Diggory
|
||||
*/
|
||||
public abstract class AbstractStoreUnivariate implements StoreUnivariate {
|
||||
|
||||
|
@ -158,6 +159,31 @@ public abstract class AbstractStoreUnivariate implements StoreUnivariate {
|
|||
return arithMean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the geometric mean for this collection of values
|
||||
* @see org.apache.commons.math.Univariate#getGeometricMean()
|
||||
*/
|
||||
public double getGeometricMean() {
|
||||
double gMean = Math.pow(getProduct(),(1.0/getN()));
|
||||
return gMean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product for this collection of values
|
||||
* @see org.apache.commons.math.Univariate#getProduct()
|
||||
*/
|
||||
public double getProduct() {
|
||||
double product = Double.NaN;
|
||||
if( getN() > 0 ) {
|
||||
product = 1.0;
|
||||
for( int i = 0; i < getN(); i++) {
|
||||
product *= getElement(i);
|
||||
}
|
||||
}
|
||||
return product;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the variance for this collection of values
|
||||
* @see org.apache.commons.math.Univariate#getVariance()
|
||||
|
|
|
@ -113,21 +113,24 @@ public class ListUnivariateImpl extends AbstractStoreUnivariate {
|
|||
double value = Double.NaN;
|
||||
if (windowSize != Univariate.INIFINTE_WINDOW &&
|
||||
windowSize < list.size()) {
|
||||
Number n = (Number) list.get(((list.size() - 1) - windowSize) +
|
||||
index) ;
|
||||
|
||||
int calcIndex = (list.size() - windowSize) + index;
|
||||
|
||||
Number n = (Number) list.get(calcIndex);
|
||||
value = n.doubleValue();
|
||||
} else {
|
||||
Number n = (Number) list.get(index);
|
||||
value = n.doubleValue();
|
||||
}
|
||||
System.out.println( "Returning value: " + value );
|
||||
return value;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.commons.math.Univariate#getN()
|
||||
*/
|
||||
public double getN() {
|
||||
double N = 0.0;
|
||||
public int getN() {
|
||||
int N = 0;
|
||||
|
||||
if (windowSize != Univariate.INIFINTE_WINDOW) {
|
||||
if (list.size() > windowSize) {
|
||||
|
|
|
@ -91,7 +91,7 @@ public class StoreUnivariateImpl extends AbstractStoreUnivariate {
|
|||
/* (non-Javadoc)
|
||||
* @see org.apache.commons.math.Univariate#getN()
|
||||
*/
|
||||
public double getN() {
|
||||
public int getN() {
|
||||
return eDA.getNumElements();
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@
|
|||
*
|
||||
* @author Phil Steitz
|
||||
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
|
||||
* @version $Revision: 1.4 $ $Date: 2003/05/20 18:15:29 $
|
||||
* @author Mark Diggory
|
||||
* @version $Revision: 1.5 $ $Date: 2003/05/21 17:59:19 $
|
||||
*
|
||||
*/
|
||||
public interface Univariate {
|
||||
|
@ -78,6 +79,18 @@ public interface Univariate {
|
|||
*/
|
||||
public abstract double getMean();
|
||||
|
||||
/**
|
||||
* Returns the geometric mean of the values that have been added
|
||||
* @return mean value
|
||||
*/
|
||||
public abstract double getGeometricMean();
|
||||
|
||||
/**
|
||||
* Returns the product of all values that have been added
|
||||
* @return product of all values
|
||||
*/
|
||||
public abstract double getProduct();
|
||||
|
||||
/**
|
||||
* Returns the variance of the values that have been added
|
||||
* @return variance value
|
||||
|
@ -103,7 +116,7 @@ public interface Univariate {
|
|||
/** Getter for property n.
|
||||
* @return Value of property n.
|
||||
*/
|
||||
public abstract double getN();
|
||||
public abstract int getN();
|
||||
|
||||
/** Getter for property sum.
|
||||
* @return Value of property sum.
|
||||
|
|
|
@ -64,7 +64,9 @@ import java.io.Serializable;
|
|||
* to doubles by addValue().
|
||||
*
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.5 $ $Date: 2003/05/20 18:15:29 $
|
||||
* @author Mark Diggory
|
||||
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
|
||||
* @version $Revision: 1.6 $ $Date: 2003/05/21 17:59:19 $
|
||||
*
|
||||
*/
|
||||
public class UnivariateImpl implements Univariate, Serializable {
|
||||
|
@ -84,7 +86,7 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
private double sumsq = 0.0;
|
||||
|
||||
/** count of values that have been added */
|
||||
private double n = 0.0;
|
||||
private int n = 0;
|
||||
|
||||
/** min of values that have been added */
|
||||
private double min = Double.MAX_VALUE;
|
||||
|
@ -92,6 +94,9 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
/** max of values that have been added */
|
||||
private double max = Double.MIN_VALUE;
|
||||
|
||||
/** produce of values that have been added */
|
||||
private double product = Double.NaN;
|
||||
|
||||
/** Creates new univariate */
|
||||
public UnivariateImpl() {
|
||||
clear();
|
||||
|
@ -118,7 +123,23 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
*/
|
||||
public double getMean() {
|
||||
// FIXME: throw something meaningful if n = 0
|
||||
return sum/n;
|
||||
return (sum / (double) n );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the geometric mean of the values that have been added
|
||||
* @return geometric mean value
|
||||
*/
|
||||
public double getGeometricMean() {
|
||||
return Math.pow(product,( 1.0/n ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product of all values add to this Univariate
|
||||
* @return product value
|
||||
*/
|
||||
public double getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +154,7 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
variance = 0.0;
|
||||
} else if( n > 1 ) {
|
||||
double xbar = getMean();
|
||||
variance = (sumsq - xbar*xbar*n)/(n-1);
|
||||
variance = (sumsq - xbar*xbar*((double) n))/(((double) n)-1);
|
||||
}
|
||||
|
||||
return variance;
|
||||
|
@ -156,18 +177,25 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
*/
|
||||
private void insertValue(double v) {
|
||||
|
||||
// The default value of product is NaN, if you
|
||||
// try to retrieve the product for a univariate with
|
||||
// no values, we return NaN.
|
||||
//
|
||||
// If this is the first call to insertValue, we want
|
||||
// to set product to 1.0, so that our first element
|
||||
// is not "cancelled" out by the NaN.
|
||||
if( n == 0 ) {
|
||||
product = 1.0;
|
||||
}
|
||||
|
||||
if( windowSize != Univariate.INIFINTE_WINDOW ) {
|
||||
|
||||
if( windowSize == n ) {
|
||||
double discarded = doubleArray.addElementRolling( v );
|
||||
|
||||
// Remove the influence of discarded value ONLY
|
||||
// if the discard value has any meaning. In other words
|
||||
// don't discount until we "roll".
|
||||
if( windowSize > doubleArray.getNumElements() ) {
|
||||
// Remove the influence of the discarded
|
||||
sum -= discarded;
|
||||
sumsq -= discarded * discarded;
|
||||
}
|
||||
// Remove the influence of the discarded
|
||||
sum -= discarded;
|
||||
sumsq -= discarded * discarded;
|
||||
|
||||
// Include the influence of the new
|
||||
// TODO: The next two lines seems rather expensive, but
|
||||
|
@ -176,6 +204,19 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
max = doubleArray.getMax();
|
||||
sum += v;
|
||||
sumsq += v*v;
|
||||
|
||||
// Note that the product CANNOT be discarded
|
||||
// properly because one cannot discount the effect
|
||||
// of a zero value. For this reason, the product
|
||||
// of the altered array must be calculated from the
|
||||
// current array elements. Product must be recalculated
|
||||
// everytime the array is "rolled"
|
||||
product = 1.0;
|
||||
double[] elements = doubleArray.getElements();
|
||||
for( int i = 0; i < elements.length; i++ ) {
|
||||
product *= elements[i];
|
||||
}
|
||||
|
||||
} else {
|
||||
doubleArray.addElement( v );
|
||||
n += 1.0;
|
||||
|
@ -183,6 +224,7 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
if (v > max) max = v;
|
||||
sum += v;
|
||||
sumsq += v*v;
|
||||
product *= v;
|
||||
}
|
||||
} else {
|
||||
// If the windowSize is inifinite please don't take the time to
|
||||
|
@ -193,6 +235,7 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
if (v > max) max = v;
|
||||
sum += v;
|
||||
sumsq += v*v;
|
||||
product *= v;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +263,7 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
/** Getter for property n.
|
||||
* @return Value of property n.
|
||||
*/
|
||||
public double getN() {
|
||||
public int getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -259,7 +302,7 @@ public class UnivariateImpl implements Univariate, Serializable {
|
|||
public void clear() {
|
||||
this.sum = 0.0;
|
||||
this.sumsq = 0.0;
|
||||
this.n = 0.0;
|
||||
this.n = 0;
|
||||
this.min = Double.MAX_VALUE;
|
||||
this.max = Double.MIN_VALUE;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ import junit.framework.TestSuite;
|
|||
* Test cases for the {@link Univariate} class.
|
||||
*
|
||||
* @author <a href="mailto:phil@steitz.com">Phil Steitz</a>
|
||||
* @version $Revision: 1.2 $ $Date: 2003/05/15 15:38:48 $
|
||||
* @version $Revision: 1.3 $ $Date: 2003/05/21 17:59:20 $
|
||||
*/
|
||||
|
||||
public final class ListUnivariateImplTest extends TestCase {
|
||||
|
@ -151,5 +151,31 @@ public final class ListUnivariateImplTest extends TestCase {
|
|||
assertEquals("skewness", 1.437424, u.getSkewness(), 0.0001);
|
||||
assertEquals("kurtosis", 2.37719, u.getKurtosis(), 0.0001);
|
||||
}
|
||||
|
||||
public void testProductAndGeometricMean() throws Exception {
|
||||
ListUnivariateImpl u = new ListUnivariateImpl(new ArrayList());
|
||||
u.setWindowSize(10);
|
||||
|
||||
u.addValue( 1.0 );
|
||||
u.addValue( 2.0 );
|
||||
u.addValue( 3.0 );
|
||||
u.addValue( 4.0 );
|
||||
|
||||
assertEquals( "Product not expected", 24.0, u.getProduct(), Double.MIN_VALUE );
|
||||
assertEquals( "Geometric mean not expected", 2.213364, u.getGeometricMean(), 0.00001 );
|
||||
|
||||
// Now test rolling - UnivariateImpl should discount the contribution
|
||||
// of a discarded element
|
||||
for( int i = 0; i < 10; i++ ) {
|
||||
u.addValue( i + 2 );
|
||||
}
|
||||
// Values should be (2,3,4,5,6,7,8,9,10,11)
|
||||
|
||||
assertEquals( "Product not expected", 39916800.0, u.getProduct(), 0.00001 );
|
||||
assertEquals( "Geometric mean not expected", 5.755931, u.getGeometricMean(), 0.00001 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ import junit.framework.TestSuite;
|
|||
* Test cases for the {@link Univariate} class.
|
||||
*
|
||||
* @author <a href="mailto:phil@steitz.com">Phil Steitz</a>
|
||||
* @version $Revision: 1.1 $ $Date: 2003/05/15 05:39:01 $
|
||||
* @version $Revision: 1.2 $ $Date: 2003/05/21 17:59:20 $
|
||||
*/
|
||||
|
||||
public final class StoreUnivariateImplTest extends TestCase {
|
||||
|
@ -142,5 +142,31 @@ public final class StoreUnivariateImplTest extends TestCase {
|
|||
assertEquals("skewness", 1.437424, u.getSkewness(), 0.0001);
|
||||
assertEquals("kurtosis", 2.37719, u.getKurtosis(), 0.0001);
|
||||
}
|
||||
|
||||
public void testProductAndGeometricMean() throws Exception {
|
||||
StoreUnivariateImpl u = new StoreUnivariateImpl();
|
||||
u.setWindowSize(10);
|
||||
|
||||
u.addValue( 1.0 );
|
||||
u.addValue( 2.0 );
|
||||
u.addValue( 3.0 );
|
||||
u.addValue( 4.0 );
|
||||
|
||||
assertEquals( "Product not expected", 24.0, u.getProduct(), Double.MIN_VALUE );
|
||||
assertEquals( "Geometric mean not expected", 2.213364, u.getGeometricMean(), 0.00001 );
|
||||
|
||||
// Now test rolling - UnivariateImpl should discount the contribution
|
||||
// of a discarded element
|
||||
for( int i = 0; i < 10; i++ ) {
|
||||
u.addValue( i + 2 );
|
||||
}
|
||||
// Values should be (2,3,4,5,6,7,8,9,10,11)
|
||||
|
||||
assertEquals( "Product not expected", 39916800.0, u.getProduct(), 0.00001 );
|
||||
assertEquals( "Geometric mean not expected", 5.755931, u.getGeometricMean(), 0.00001 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ import junit.framework.TestSuite;
|
|||
* Test cases for the {@link Univariate} class.
|
||||
*
|
||||
* @author <a href="mailto:phil@steitz.com">Phil Steitz</a>
|
||||
* @version $Revision: 1.1 $ $Date: 2003/05/15 05:39:01 $
|
||||
* @version $Revision: 1.2 $ $Date: 2003/05/21 17:59:20 $
|
||||
*/
|
||||
|
||||
public final class UnivariateImplTest extends TestCase {
|
||||
|
@ -125,5 +125,30 @@ public final class UnivariateImplTest extends TestCase {
|
|||
assertTrue( "Mean of n = 1 set should be zero", u.getStandardDeviation() == 0);
|
||||
assertTrue( "Variance of n = 1 set should be zero", u.getVariance() == 0);
|
||||
}
|
||||
|
||||
public void testProductAndGeometricMean() throws Exception {
|
||||
UnivariateImpl u = new UnivariateImpl(10);
|
||||
|
||||
u.addValue( 1.0 );
|
||||
u.addValue( 2.0 );
|
||||
u.addValue( 3.0 );
|
||||
u.addValue( 4.0 );
|
||||
|
||||
assertEquals( "Product not expected", 24.0, u.getProduct(), Double.MIN_VALUE );
|
||||
assertEquals( "Geometric mean not expected", 2.213364, u.getGeometricMean(), 0.00001 );
|
||||
|
||||
// Now test rolling - UnivariateImpl should discount the contribution
|
||||
// of a discarded element
|
||||
for( int i = 0; i < 10; i++ ) {
|
||||
u.addValue( i + 2 );
|
||||
}
|
||||
// Values should be (2,3,4,5,6,7,8,9,10,11)
|
||||
|
||||
assertEquals( "Product not expected", 39916800.0, u.getProduct(), 0.00001 );
|
||||
assertEquals( "Geometric mean not expected", 5.755931, u.getGeometricMean(), 0.00001 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ import java.net.URL;
|
|||
* Test cases for the ValueServer class.
|
||||
*
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.1 $
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
|
||||
public final class ValueServerTest extends TestCase {
|
||||
|
@ -105,9 +105,9 @@ public final class ValueServerTest extends TestCase {
|
|||
next = vs.getNext();
|
||||
stats.addValue(next);
|
||||
}
|
||||
assertEquals("mean", stats.getMean(),5.069831575018909,tolerance);
|
||||
assertEquals("mean", 5.069831575018909, stats.getMean(), tolerance);
|
||||
assertEquals
|
||||
("std dev", stats.getStandardDeviation(),1.0173699343977738,tolerance);
|
||||
("std dev", 1.0173699343977738, stats.getStandardDeviation(), tolerance);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue