Author: psteitz
Date: Tue Dec 29 19:57:49 2009
New Revision: 894472
URL: http://svn.apache.org/viewvc?rev=894472&view=rev
Log:
Added WeightedEvaluation interface and added evaluate(values, weights) to
weighted statistics implementations. JIRA: MATH-287.
Added:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
(with props)
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Mean.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Variance.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Product.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Sum.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/descriptive/UnivariateStatisticAbstractTest.java
Added:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java?rev=894472&view=auto
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
(added)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
Tue Dec 29 19:57:49 2009
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math.stat.descriptive;
+
+/**
+ * Weighted evaluation for statistics.
+ *
+ * @since 2.1
+ * @version $Revision$ $Date$
+ */
+public interface WeightedEvaluation {
+
+ /**
+ * Returns the result of evaluating the statistic over the input array,
+ * using the supplied weights.
+ *
+ * @param values input array
+ * @param weights array of weights
+ * @return the value of the statistic applied to the input array
+ */
+ double evaluate(double[] values, double[] weights);
+
+ /**
+ * Returns the result of evaluating the statistic over the specified
entries
+ * in the input array, using corresponding entries in the supplied weights
array.
+ *
+ * @param values the input array
+ * @param weights array of weights
+ * @param begin the index of the first element to include
+ * @param length the number of elements to include
+ * @return the value of the statistic applied to the included array entries
+ */
+ double evaluate(double[] values, double[] weights, int begin, int length);
+
+}
Propchange:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/WeightedEvaluation.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Mean.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Mean.java?rev=894472&r1=894471&r2=894472&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Mean.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Mean.java
Tue Dec 29 19:57:49 2009
@@ -19,6 +19,7 @@
import java.io.Serializable;
import
org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
+import org.apache.commons.math.stat.descriptive.WeightedEvaluation;
import org.apache.commons.math.stat.descriptive.summary.Sum;
/**
@@ -56,7 +57,7 @@
* @version $Revision$ $Date$
*/
public class Mean extends AbstractStorelessUnivariateStatistic
- implements Serializable {
+ implements Serializable, WeightedEvaluation {
/** Serializable version identifier */
private static final long serialVersionUID = -1296043746617791564L;
@@ -214,6 +215,33 @@
}
return Double.NaN;
}
+
+ /**
+ * Returns the weighted arithmetic mean of the entries in the input array.
+ * <p>
+ * Throws <code>IllegalArgumentException</code> if either array is
null.</p>
+ * <p>
+ * See {...@link Mean} for details on the computing algorithm. The
two-pass algorithm
+ * described above is used here, with weights applied in computing both
the original
+ * estimate and the correction factor.</p>
+ * <p>
+ * Throws <code>IllegalArgumentException</code> if any of the following
are true:
+ * <ul><li>the values array is null</li>
+ * <li>the weights array is null</li>
+ * <li>the weights array does not have the same length as the values
array</li>
+ * <li>the weights array contains one or more infinite values</li>
+ * <li>the weights array contains one or more NaN values</li>
+ * <li>the weights array contains negative values</li>
+ * </ul></p>
+ *
+ * @param values the input array
+ * @param weights the weights array
+ * @return the mean of the values or Double.NaN if length = 0
+ * @throws IllegalArgumentException if the parameters are not valid
+ */
+ public double evaluate(final double[] values, final double[] weights) {
+ return evaluate(values, weights, 0, values.length);
+ }
/**
* {...@inheritdoc}
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Variance.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Variance.java?rev=894472&r1=894471&r2=894472&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Variance.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/moment/Variance.java
Tue Dec 29 19:57:49 2009
@@ -19,6 +19,7 @@
import java.io.Serializable;
import org.apache.commons.math.MathRuntimeException;
+import org.apache.commons.math.stat.descriptive.WeightedEvaluation;
import
org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
/**
@@ -63,7 +64,7 @@
*
* @version $Revision$ $Date$
*/
-public class Variance extends AbstractStorelessUnivariateStatistic implements
Serializable {
+public class Variance extends AbstractStorelessUnivariateStatistic implements
Serializable, WeightedEvaluation {
/** Serializable version identifier */
private static final long serialVersionUID = -9111962718267217978L;
@@ -293,7 +294,7 @@
* @param weights the weights array
* @param begin index of the first array element to include
* @param length the number of elements to include
- * @return the variance of the values or Double.NaN if length = 0
+ * @return the weighted variance of the values or Double.NaN if length = 0
* @throws IllegalArgumentException if the parameters are not valid
*/
public double evaluate(final double[] values, final double[] weights,
@@ -313,6 +314,47 @@
}
return var;
}
+
+ /**
+ * <p>
+ * Returns the weighted variance of the entries in the the input array.</p>
+ * <p>
+ * Uses the formula <pre>
+ * Σ(weights[i]*(values[i] -
weightedMean)<sup>2</sup>)/(Σ(weights[i]) - 1)
+ * </pre>
+ * where weightedMean is the weighted mean</p>
+ * <p>
+ * This formula will not return the same result as the unweighted variance
when all
+ * weights are equal, unless all weights are equal to 1. The formula
assumes that
+ * weights are to be treated as "expansion values," as will be the case if
for example
+ * the weights represent frequency counts. To normalize weights so that
the denominator
+ * in the variance computation equals the length of the input vector minus
one, use <pre>
+ * <code>evaluate(values, MathUtils.normalizeArray(weights,
values.length)); </code>
+ * </pre>
+ * <p>
+ * Returns 0 for a single-value (i.e. length = 1) sample.</p>
+ * <p>
+ * Throws <code>IllegalArgumentException</code> if any of the following
are true:
+ * <ul><li>the values array is null</li>
+ * <li>the weights array is null</li>
+ * <li>the weights array does not have the same length as the values
array</li>
+ * <li>the weights array contains one or more infinite values</li>
+ * <li>the weights array contains one or more NaN values</li>
+ * <li>the weights array contains negative values</li>
+ * </ul></p>
+ * <p>
+ * Does not change the internal state of the statistic.</p>
+ * <p>
+ * Throws <code>IllegalArgumentException</code> if either array is
null.</p>
+ *
+ * @param values the input array
+ * @param weights the weights array
+ * @return the weighted variance of the values
+ * @throws IllegalArgumentException if the parameters are not valid
+ */
+ public double evaluate(final double[] values, final double[] weights) {
+ return evaluate(values, weights, 0, values.length);
+ }
/**
* Returns the variance of the entries in the specified portion of
@@ -367,6 +409,35 @@
}
return var;
}
+
+ /**
+ * Returns the variance of the entries in the input array, using the
+ * precomputed mean value. Returns <code>Double.NaN</code> if the array
+ * is empty.
+ * <p>
+ * See {...@link Variance} for details on the computing algorithm.</p>
+ * <p>
+ * If <code>isBiasCorrected</code> is <code>true</code> the formula used
+ * assumes that the supplied mean value is the arithmetic mean of the
+ * sample data, not a known population parameter. If the mean is a known
+ * population parameter, or if the "population" version of the variance is
+ * desired, set <code>isBiasCorrected</code> to <code>false</code> before
+ * invoking this method.</p>
+ * <p>
+ * Returns 0 for a single-value (i.e. length = 1) sample.</p>
+ * <p>
+ * Throws <code>IllegalArgumentException</code> if the array is null.</p>
+ * <p>
+ * Does not change the internal state of the statistic.</p>
+ *
+ * @param values the input array
+ * @param mean the precomputed mean value
+ * @return the variance of the values or Double.NaN if the array is empty
+ * @throws IllegalArgumentException if the array is null
+ */
+ public double evaluate(final double[] values, final double mean) {
+ return evaluate(values, mean, 0, values.length);
+ }
/**
* Returns the weighted variance of the entries in the specified portion of
@@ -387,7 +458,7 @@
* weights are to be treated as "expansion values," as will be the case if
for example
* the weights represent frequency counts. To normalize weights so that
the denominator
* in the variance computation equals the length of the input vector minus
one, use <pre>
- * <code>evaluate(values, MathUtils.normalizeArray(weights,
values.length)); </code>
+ * <code>evaluate(values, MathUtils.normalizeArray(weights,
values.length), mean); </code>
* </pre>
* <p>
* Returns 0 for a single-value (i.e. length = 1) sample.</p>
@@ -442,34 +513,49 @@
}
return var;
}
-
+
/**
- * Returns the variance of the entries in the input array, using the
- * precomputed mean value. Returns <code>Double.NaN</code> if the array
- * is empty.
+ * <p>Returns the weighted variance of the values in the input array, using
+ * the precomputed weighted mean value.</p>
* <p>
- * See {...@link Variance} for details on the computing algorithm.</p>
+ * Uses the formula <pre>
+ * Σ(weights[i]*(values[i] -
mean)<sup>2</sup>)/(Σ(weights[i]) - 1)
+ * </pre></p>
* <p>
- * If <code>isBiasCorrected</code> is <code>true</code> the formula used
- * assumes that the supplied mean value is the arithmetic mean of the
- * sample data, not a known population parameter. If the mean is a known
- * population parameter, or if the "population" version of the variance is
- * desired, set <code>isBiasCorrected</code> to <code>false</code> before
- * invoking this method.</p>
+ * The formula used assumes that the supplied mean value is the weighted
arithmetic
+ * mean of the sample data, not a known population parameter. This method
+ * is supplied only to save computation when the mean has already been
+ * computed.</p>
+ * <p>
+ * This formula will not return the same result as the unweighted variance
when all
+ * weights are equal, unless all weights are equal to 1. The formula
assumes that
+ * weights are to be treated as "expansion values," as will be the case if
for example
+ * the weights represent frequency counts. To normalize weights so that
the denominator
+ * in the variance computation equals the length of the input vector minus
one, use <pre>
+ * <code>evaluate(values, MathUtils.normalizeArray(weights,
values.length), mean); </code>
+ * </pre>
* <p>
* Returns 0 for a single-value (i.e. length = 1) sample.</p>
* <p>
- * Throws <code>IllegalArgumentException</code> if the array is null.</p>
+ * Throws <code>IllegalArgumentException</code> if any of the following
are true:
+ * <ul><li>the values array is null</li>
+ * <li>the weights array is null</li>
+ * <li>the weights array does not have the same length as the values
array</li>
+ * <li>the weights array contains one or more infinite values</li>
+ * <li>the weights array contains one or more NaN values</li>
+ * <li>the weights array contains negative values</li>
+ * </ul></p>
* <p>
* Does not change the internal state of the statistic.</p>
*
* @param values the input array
- * @param mean the precomputed mean value
- * @return the variance of the values or Double.NaN if the array is empty
- * @throws IllegalArgumentException if the array is null
+ * @param weights the weights array
+ * @param mean the precomputed weighted mean value
+ * @return the variance of the values or Double.NaN if length = 0
+ * @throws IllegalArgumentException if the parameters are not valid
*/
- public double evaluate(final double[] values, final double mean) {
- return evaluate(values, mean, 0, values.length);
+ public double evaluate(final double[] values, final double[] weights,
final double mean) {
+ return evaluate(values, weights, mean, 0, values.length);
}
/**
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Product.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Product.java?rev=894472&r1=894471&r2=894472&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Product.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Product.java
Tue Dec 29 19:57:49 2009
@@ -19,6 +19,7 @@
import java.io.Serializable;
import
org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
+import org.apache.commons.math.stat.descriptive.WeightedEvaluation;
/**
* Returns the product of the available values.
@@ -33,7 +34,7 @@
*
* @version $Revision$ $Date$
*/
-public class Product extends AbstractStorelessUnivariateStatistic implements
Serializable {
+public class Product extends AbstractStorelessUnivariateStatistic implements
Serializable, WeightedEvaluation {
/** Serializable version identifier */
private static final long serialVersionUID = 2824226005990582538L;
@@ -165,6 +166,33 @@
}
return product;
}
+
+ /**
+ * <p>Returns the weighted product of the entries in the input array.</p>
+ *
+ * <p>Throws <code>IllegalArgumentException</code> if any of the following
are true:
+ * <ul><li>the values array is null</li>
+ * <li>the weights array is null</li>
+ * <li>the weights array does not have the same length as the values
array</li>
+ * <li>the weights array contains one or more infinite values</li>
+ * <li>the weights array contains one or more NaN values</li>
+ * <li>the weights array contains negative values</li>
+ * </ul></p>
+ *
+ * <p>Uses the formula, <pre>
+ * weighted product = ∏values[i]<sup>weights[i]</sup>
+ * </pre>
+ * that is, the weights are applied as exponents when computing the
weighted product.</p>
+ *
+ * @param values the input array
+ * @param weights the weights array
+ * @return the product of the values or Double.NaN if length = 0
+ * @throws IllegalArgumentException if the parameters are not valid
+ */
+ public double evaluate(final double[] values, final double[] weights) {
+ return evaluate(values, weights, 0, values.length);
+ }
+
/**
* {...@inheritdoc}
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Sum.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Sum.java?rev=894472&r1=894471&r2=894472&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Sum.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/descriptive/summary/Sum.java
Tue Dec 29 19:57:49 2009
@@ -19,6 +19,8 @@
import java.io.Serializable;
import
org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
+import org.apache.commons.math.stat.descriptive.WeightedEvaluation;
+
/**
* Returns the sum of the available values.
@@ -164,6 +166,31 @@
}
return sum;
}
+
+ /**
+ * The weighted sum of the entries in the the input array.
+ * <p>
+ * Throws <code>IllegalArgumentException</code> if any of the following
are true:
+ * <ul><li>the values array is null</li>
+ * <li>the weights array is null</li>
+ * <li>the weights array does not have the same length as the values
array</li>
+ * <li>the weights array contains one or more infinite values</li>
+ * <li>the weights array contains one or more NaN values</li>
+ * <li>the weights array contains negative values</li>
+ * </ul></p>
+ * <p>
+ * Uses the formula, <pre>
+ * weighted sum = Σ(values[i] * weights[i])
+ * </pre></p>
+ *
+ * @param values the input array
+ * @param weights the weights array
+ * @return the sum of the values or Double.NaN if length = 0
+ * @throws IllegalArgumentException if the parameters are not valid
+ */
+ public double evaluate(final double[] values, final double[] weights) {
+ return evaluate(values, weights, 0, values.length);
+ }
/**
* {...@inheritdoc}
Modified:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/descriptive/UnivariateStatisticAbstractTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/descriptive/UnivariateStatisticAbstractTest.java?rev=894472&r1=894471&r2=894472&view=diff
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/descriptive/UnivariateStatisticAbstractTest.java
(original)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/descriptive/UnivariateStatisticAbstractTest.java
Tue Dec 29 19:57:49 2009
@@ -126,12 +126,8 @@
// See if this statistic computes weighted statistics
// If not, skip this test
UnivariateStatistic statistic = getUnivariateStatistic();
- Method evaluateMethod = null;
- try {
- evaluateMethod = statistic.getClass().getDeclaredMethod("evaluate",
- double[].class, double[].class, int.class, int.class);
- } catch (NoSuchMethodException ex) {
- return; // skip test
+ if (!(statistic instanceof WeightedEvaluation)) {
+ return;
}
// Create arrays of values and corresponding integral weights
@@ -171,10 +167,14 @@
// Compare result of weighted statistic computation with direct
computation
// on array of repeated values
- double weightedResult = (Double) evaluateMethod.invoke(
- statistic, values, weights, 0, values.length);
- TestUtils.assertRelativelyEquals(
- statistic.evaluate(repeatedValues), weightedResult, 10E-14);
+ WeightedEvaluation weightedStatistic = (WeightedEvaluation) statistic;
+ TestUtils.assertRelativelyEquals(statistic.evaluate(repeatedValues),
+ weightedStatistic.evaluate(values, weights, 0, values.length),
+ 10E-14);
+
+ // Check consistency of weighted evaluation methods
+ assertEquals(weightedStatistic.evaluate(values, weights, 0,
values.length),
+ weightedStatistic.evaluate(values, weights),
Double.MIN_VALUE);
}