Added AggregateSummaryStatistics class to support aggregation of SummaryStatistics.

JIRA: MATH-224
Reported by Andre Panisson
Patched by John Bollinger


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@768921 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2009-04-27 10:51:52 +00:00
parent 6f47f883d6
commit 4566fcf22c
4 changed files with 324 additions and 0 deletions

View File

@ -105,6 +105,9 @@
<contributor>
<name>R&#233;mi Arntzen</name>
</contributor>
<contributor>
<name>John Bollinger</name>
</contributor>
<contributor>
<name>Cyril Briquet</name>
</contributor>

View File

@ -0,0 +1,245 @@
/*
* 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;
import java.io.Serializable;
/**
* <p>
* A StatisticalSummary that aggregates statistics from several data sets or
* data set partitions. In its simplest usage mode, the client creates an
* instance via the zero-argument constructor, then uses
* {@link #createContributingStatistics()} to obtain a {@code SummaryStatistics}
* for each individual data set / partition. The per-set statistics objects
* are used as normal, and at any time the aggregate statistics for all the
* contributors can be obtained from this object.
* </p><p>
* Clients with specialized requirements can use alternative constructors to
* control the statistics implementations and initial values used by the
* contributing and the internal aggregate {@code SummaryStatistics} objects.
* </p>
*
* @since 2.0
* @version $Revision:$ $Date:$
*
*/
public class AggregateSummaryStatistics implements StatisticalSummary,
Serializable {
/**
* The serialization version of this class
*/
private static final long serialVersionUID = 1L;
/**
* A SummaryStatistics serving as a prototype for creating SummaryStatistics
* contributing to this aggregate
*/
private SummaryStatistics statisticsPrototype;
/**
* The SummaryStatistics in which aggregate statistics are accumulated
*/
private SummaryStatistics statistics;
/**
* Initializes a new AggregateSummaryStatistics with default statistics
* implementations.
*
* @see SummaryStatistics#SummaryStatistics()
*/
public AggregateSummaryStatistics() {
this(new SummaryStatistics());
}
/**
* Initializes a new AggregateSummaryStatistics with the specified statistics
* object as a prototype for contributing statistics and for the internal
* aggregate statistics. This provides for customized statistics implementations
* to be used by contributing and aggregate statistics.
*
* @param prototypeStatistics a {@code SummaryStatistics} serving as a
* prototype both for the internal aggregate statistics and for
* contributing statistics obtained via the
* {@code createContributingStatistics()} method. Being a prototype
* means that other objects are initialized by copying this object's state.
* If {@code null}, a new, default statistics object is used. Any statistic
* values in the prototype are propagated to contributing statistics
* objects and (once) into these aggregate statistics.
* @see #createContributingStatistics()
*/
public AggregateSummaryStatistics(SummaryStatistics prototypeStatistics) {
this(prototypeStatistics, (prototypeStatistics == null ? null :
new SummaryStatistics(prototypeStatistics)));
}
/**
* Initializes a new AggregateSummaryStatistics with the specified statistics
* object as a prototype for contributing statistics and for the internal
* aggregate statistics. This provides for different statistics implementations
* to be used by contributing and aggregate statistics and for an initial
* state to be supplied for the aggregate statistics.
*
* @param prototypeStatistics a {@code SummaryStatistics} serving as a
* prototype both for the internal aggregate statistics and for
* contributing statistics obtained via the
* {@code createContributingStatistics()} method. Being a prototype
* means that other objects are initialized by copying this object's state.
* If {@code null}, a new, default statistics object is used. Any statistic
* values in the prototype are propagated to contributing statistics
* objects, but not into these aggregate statistics.
* @param initialStatistics a {@code SummaryStatistics} to serve as the
* internal aggregate statistics object. If {@code null}, a new, default
* statistics object is used.
* @see #createContributingStatistics()
*/
public AggregateSummaryStatistics(SummaryStatistics prototypeStatistics,
SummaryStatistics initialStatistics) {
this.statisticsPrototype = ((prototypeStatistics == null) ?
new SummaryStatistics() : prototypeStatistics);
this.statistics = ((initialStatistics == null) ?
new SummaryStatistics() : initialStatistics);
}
/**
* {@inheritDoc}. This version returns the maximum over all the aggregated
* data.
*
* @see StatisticalSummary#getMax()
*/
public double getMax() {
return statistics.getMax();
}
/**
* {@inheritDoc}. This version returns the mean of all the aggregated data.
*
* @see StatisticalSummary#getMean()
*/
public double getMean() {
return statistics.getMean();
}
/**
* {@inheritDoc}. This version returns the minimum over all the aggregated
* data.
*
* @see StatisticalSummary#getMin()
*/
public double getMin() {
return statistics.getMin();
}
/**
* {@inheritDoc}. This version returns a count of all the aggregated data.
*
* @see StatisticalSummary#getN()
*/
public long getN() {
return statistics.getN();
}
/**
* {@inheritDoc}. This version returns the standard deviation of all the
* aggregated data.
*
* @see StatisticalSummary#getStandardDeviation()
*/
public double getStandardDeviation() {
return statistics.getStandardDeviation();
}
/**
* {@inheritDoc}. This version returns a sum of all the aggregated data.
*
* @see StatisticalSummary#getSum()
*/
public double getSum() {
return statistics.getSum();
}
/**
* {@inheritDoc}. This version returns the variance of all the aggregated
* data.
*
* @see StatisticalSummary#getVariance()
*/
public double getVariance() {
return statistics.getVariance();
}
/**
* Creates and returns a {@code SummaryStatistics} whose data will be
* aggregated with those of this {@code AggregateSummaryStatistics}.
*
* @return a {@code SummaryStatistics} whose data will be aggregated with
* those of this {@code AggregateSummaryStatistics}. The initial state
* is a copy of the configured prototype statistics.
*/
public SummaryStatistics createContributingStatistics() {
SummaryStatistics contributingStatistics
= new AggregatingSummaryStatistics(statistics);
SummaryStatistics.copy(statisticsPrototype, contributingStatistics);
return contributingStatistics;
}
/**
* A SummaryStatistics that also forwards all values added to it to a second
* {@code SummaryStatistics} for aggregation.
*
* @since 2.0
*/
private static class AggregatingSummaryStatistics extends SummaryStatistics {
/**
* The serialization version of this class
*/
private static final long serialVersionUID = 1L;
/**
* An additional SummaryStatistics into which values added to these
* statistics (and possibly others) are aggregated
*/
private SummaryStatistics aggregateStatistics;
/**
* Initializes a new AggregatingSummaryStatistics with the specified
* aggregate statistics object
*
* @param aggregateStatistics a {@code SummaryStatistics} into which
* values added to this statistics object should be aggregated
*/
public AggregatingSummaryStatistics(SummaryStatistics aggregateStatistics) {
this.aggregateStatistics = aggregateStatistics;
}
/**
* {@inheritDoc}. This version adds the provided value to the configured
* aggregate after adding it to these statistics.
*
* @see SummaryStatistics#addValue(double)
*/
@Override
public void addValue(double value) {
super.addValue(value);
aggregateStatistics.addValue(value);
}
}
}

View File

@ -43,6 +43,9 @@ The <action> type attribute can be add,update,fix,remove.
Added support for any type of field in linear algebra (FielxMatrix, FieldVector,
FieldLUDecomposition)
</action>
<action dev="psteitz" type="add" due-to="John Bollinger">
Added AggregateSummaryStatistics class to support aggregation of SummaryStatistics.
</action>
<action dev="luc" type="add" >
Added general Field and FieldElement interfaces to allow generic algorithms
to operate on fields. The library already provides several implementations:

View File

@ -0,0 +1,73 @@
/*
* 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;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Test cases for {@link AggregateSummaryStatistics}
*
*/
public class AggregateSummaryStatisticsTest extends TestCase {
/**
* Tests the standard aggregation behavior
*/
public void testAggregation() {
AggregateSummaryStatistics aggregate = new AggregateSummaryStatistics();
SummaryStatistics setOneStats = aggregate.createContributingStatistics();
SummaryStatistics setTwoStats = aggregate.createContributingStatistics();
assertNotNull("The set one contributing stats are null", setOneStats);
assertNotNull("The set two contributing stats are null", setTwoStats);
assertNotSame("Contributing stats objects are the same", setOneStats, setTwoStats);
setOneStats.addValue(2);
setOneStats.addValue(3);
setOneStats.addValue(5);
setOneStats.addValue(7);
setOneStats.addValue(11);
assertEquals("Wrong number of set one values", 5, setOneStats.getN());
assertEquals("Wrong sum of set one values", 28.0, setOneStats.getSum());
setTwoStats.addValue(2);
setTwoStats.addValue(4);
setTwoStats.addValue(8);
assertEquals("Wrong number of set two values", 3, setTwoStats.getN());
assertEquals("Wrong sum of set two values", 14.0, setTwoStats.getSum());
assertEquals("Wrong number of aggregate values", 8, aggregate.getN());
assertEquals("Wrong aggregate sum", 42.0, aggregate.getSum());
}
/**
* Creates and returns a {@code Test} representing all the test cases in this
* class
*
* @return a {@code Test} representing all the test cases in this class
*/
public static Test suite() {
TestSuite suite = new TestSuite(AggregateSummaryStatisticsTest.class);
suite.setName("AggregateSummaryStatistics tests");
return suite;
}
}