added multivariate summary statistics
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@619934 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ac6a598144
commit
1cabcd496c
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
* 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;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.math.DimensionMismatchException;
|
||||
import org.apache.commons.math.linear.RealMatrix;
|
||||
import org.apache.commons.math.stat.descriptive.moment.GeometricMean;
|
||||
import org.apache.commons.math.stat.descriptive.moment.Mean;
|
||||
import org.apache.commons.math.stat.descriptive.moment.VectorialCovariance;
|
||||
import org.apache.commons.math.stat.descriptive.rank.Max;
|
||||
import org.apache.commons.math.stat.descriptive.rank.Min;
|
||||
import org.apache.commons.math.stat.descriptive.summary.Sum;
|
||||
import org.apache.commons.math.stat.descriptive.summary.SumOfLogs;
|
||||
import org.apache.commons.math.stat.descriptive.summary.SumOfSquares;
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
* <p>Computes summary statistics for a stream of data values added using the
|
||||
* {@link #addValue(double[]) addValue} method. The data values are not stored in
|
||||
* memory, so this class can be used to compute statistics for very large
|
||||
* data streams.</p>
|
||||
*
|
||||
* <p>The {@link StorelessUnivariateStatistic} array instances used to maintain
|
||||
* summary state and compute statistics are configurable via setters.
|
||||
* For example, the default implementation for the mean can be overridden by
|
||||
* calling {@link #setMeanImpl(StorelessUnivariateStatistic[])}. Actual
|
||||
* parameters to these methods must implement the
|
||||
* {@link StorelessUnivariateStatistic} interface and configuration must be
|
||||
* completed before <code>addValue</code> is called. No configuration is
|
||||
* necessary to use the default, commons-math provided implementations.</p>
|
||||
*
|
||||
* <p>Note: This class is not thread-safe. Use
|
||||
* {@link SynchronizedMultivariateSummaryStatistics} if concurrent access from multiple
|
||||
* threads is required.</p>
|
||||
*
|
||||
* @since 1.2
|
||||
* @version $Revision: 618097 $ $Date: 2008-02-03 22:39:08 +0100 (dim., 03 févr. 2008) $
|
||||
*/
|
||||
public class MultivariateSummaryStatistics
|
||||
implements StatisticalMultivariateSummary, Serializable {
|
||||
|
||||
/** Serialization UID */
|
||||
private static final long serialVersionUID = 2271900808994826718L;
|
||||
|
||||
/**
|
||||
* Construct a MultivariateSummaryStatistics instance
|
||||
* @param k dimension of the data
|
||||
* @param isCovarianceBiasCorrected if true, the unbiased sample
|
||||
* covariance is computed, otherwise the biased population covariance
|
||||
* is computed
|
||||
*/
|
||||
public MultivariateSummaryStatistics(int k, boolean isCovarianceBiasCorrected) {
|
||||
this.k = k;
|
||||
|
||||
sumImpl = new StorelessUnivariateStatistic[k];
|
||||
sumSqImpl = new StorelessUnivariateStatistic[k];
|
||||
minImpl = new StorelessUnivariateStatistic[k];
|
||||
maxImpl = new StorelessUnivariateStatistic[k];
|
||||
sumLogImpl = new StorelessUnivariateStatistic[k];
|
||||
geoMeanImpl = new StorelessUnivariateStatistic[k];
|
||||
meanImpl = new StorelessUnivariateStatistic[k];
|
||||
|
||||
for (int i = 0; i < k; ++i) {
|
||||
sumImpl[i] = new Sum();
|
||||
sumSqImpl[i] = new SumOfSquares();
|
||||
minImpl[i] = new Min();
|
||||
maxImpl[i] = new Max();
|
||||
sumLogImpl[i] = new SumOfLogs();
|
||||
geoMeanImpl[i] = new GeometricMean();
|
||||
meanImpl[i] = new Mean();
|
||||
}
|
||||
|
||||
covarianceImpl =
|
||||
new VectorialCovariance(k, isCovarianceBiasCorrected);
|
||||
|
||||
}
|
||||
|
||||
/** Dimension of the data. */
|
||||
private int k;
|
||||
|
||||
/** Count of values that have been added */
|
||||
private long n = 0;
|
||||
|
||||
/** Sum statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] sumImpl;
|
||||
|
||||
/** Sum of squares statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] sumSqImpl;
|
||||
|
||||
/** Minimum statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] minImpl;
|
||||
|
||||
/** Maximum statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] maxImpl;
|
||||
|
||||
/** Sum of log statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] sumLogImpl;
|
||||
|
||||
/** Geometric mean statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] geoMeanImpl;
|
||||
|
||||
/** Mean statistic implementation - can be reset by setter. */
|
||||
private StorelessUnivariateStatistic[] meanImpl;
|
||||
|
||||
/** Covariance statistic implementation - cannot be reset. */
|
||||
private VectorialCovariance covarianceImpl;
|
||||
|
||||
/**
|
||||
* Return a {@link StatisticalMultivariateSummary} instance reporting current
|
||||
* statistics.
|
||||
*
|
||||
* @return Current values of statistics
|
||||
*/
|
||||
public StatisticalMultivariateSummary getSummary() {
|
||||
return new StatisticalMultivariateSummaryValues(getDimension(), getMean(),
|
||||
getCovariance(), getStandardDeviation(),
|
||||
getN(), getMax(), getMin(),
|
||||
getSum(), getSumSq(), getSumLog());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a value to the data
|
||||
*
|
||||
* @param value the value to add
|
||||
* @throws DimensionMismatchException if the value dimension
|
||||
* does not match the one used at construction
|
||||
*/
|
||||
public void addValue(double[] value)
|
||||
throws DimensionMismatchException {
|
||||
if (value.length != k) {
|
||||
throw new DimensionMismatchException(value.length, k);
|
||||
}
|
||||
|
||||
for (int i = 0; i < k; ++i) {
|
||||
double v = value[i];
|
||||
sumImpl[i].increment(v);
|
||||
sumSqImpl[i].increment(v);
|
||||
minImpl[i].increment(v);
|
||||
maxImpl[i].increment(v);
|
||||
sumLogImpl[i].increment(v);
|
||||
geoMeanImpl[i].increment(v);
|
||||
meanImpl[i].increment(v);
|
||||
}
|
||||
covarianceImpl.increment(value);
|
||||
n++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimension of the data
|
||||
* @return The dimension of the data
|
||||
*/
|
||||
public int getDimension() {
|
||||
return k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of available values
|
||||
* @return The number of available values
|
||||
*/
|
||||
public long getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of the results of a statistic.
|
||||
* @param stats univariate statistic array
|
||||
* @return results array
|
||||
*/
|
||||
private double[] getResults(StorelessUnivariateStatistic[] stats) {
|
||||
double[] results = new double[stats.length];
|
||||
for (int i = 0; i < results.length; ++i) {
|
||||
results[i] = stats[i].getResult();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of the values that have been added
|
||||
* @return The sum or <code>Double.NaN</code> if no values have been added
|
||||
*/
|
||||
public double[] getSum() {
|
||||
return getResults(sumImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of the squares of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return The sum of squares
|
||||
*/
|
||||
public double[] getSumSq() {
|
||||
return getResults(sumSqImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of the logarithms of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return The sum of logarithms
|
||||
*/
|
||||
public double[] getSumLog() {
|
||||
return getResults(sumLogImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mean of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return the mean
|
||||
*/
|
||||
public double[] getMean() {
|
||||
return getResults(meanImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard deviation of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return the standard deviation
|
||||
*/
|
||||
public double[] getStandardDeviation() {
|
||||
double[] stdDev = new double[k];
|
||||
if (getN() < 1) {
|
||||
Arrays.fill(stdDev, Double.NaN);
|
||||
} else if (getN() < 2) {
|
||||
Arrays.fill(stdDev, 0.0);
|
||||
} else {
|
||||
RealMatrix matrix = covarianceImpl.getResult();
|
||||
for (int i = 0; i < k; ++i) {
|
||||
stdDev[i] = Math.sqrt(matrix.getEntry(i, i));
|
||||
}
|
||||
}
|
||||
return stdDev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the covariance of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return the variance
|
||||
*/
|
||||
public RealMatrix getCovariance() {
|
||||
return covarianceImpl.getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return the maximum
|
||||
*/
|
||||
public double[] getMax() {
|
||||
return getResults(maxImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return the minimum
|
||||
*/
|
||||
public double[] getMin() {
|
||||
return getResults(minImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the geometric mean of the values that have been added.
|
||||
* <p>
|
||||
* Double.NaN is returned if no values have been added.</p>
|
||||
*
|
||||
* @return the geometric mean
|
||||
*/
|
||||
public double[] getGeometricMean() {
|
||||
return getResults(geoMeanImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a text report displaying
|
||||
* summary statistics from values that
|
||||
* have been added.
|
||||
* @return String with line feeds displaying statistics
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer outBuffer = new StringBuffer();
|
||||
outBuffer.append("MultivariateSummaryStatistics:\n");
|
||||
outBuffer.append("n: " + getN() + "\n");
|
||||
append(outBuffer, getMin(), "min: ", ", ", "\n");
|
||||
append(outBuffer, getMax(), "max: ", ", ", "\n");
|
||||
append(outBuffer, getMean(), "mean: ", ", ", "\n");
|
||||
append(outBuffer, getGeometricMean(), "geometric mean: ", ", ", "\n");
|
||||
append(outBuffer, getSumSq(), "sum of squares: ", ", ", "\n");
|
||||
append(outBuffer, getSumLog(), "sum of logarithms: ", ", ", "\n");
|
||||
append(outBuffer, getStandardDeviation(), "standard deviation: ", ", ", "\n");
|
||||
outBuffer.append("covariance: " + getCovariance().toString() + "\n");
|
||||
return outBuffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a text representation of an array to a buffer.
|
||||
* @param buffer buffer to fill
|
||||
* @param data data array
|
||||
* @param prefix text prefix
|
||||
* @param separator elements separator
|
||||
* @param suffix text suffix
|
||||
*/
|
||||
private void append(StringBuffer buffer, double[] data,
|
||||
String prefix, String separator, String suffix) {
|
||||
buffer.append(prefix);
|
||||
for (int i = 0; i < data.length; ++i) {
|
||||
if (i > 0) {
|
||||
buffer.append(separator);
|
||||
}
|
||||
buffer.append(data[i]);
|
||||
}
|
||||
buffer.append(suffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all statistics and storage
|
||||
*/
|
||||
public void clear() {
|
||||
this.n = 0;
|
||||
for (int i = 0; i < k; ++i) {
|
||||
minImpl[i].clear();
|
||||
maxImpl[i].clear();
|
||||
sumImpl[i].clear();
|
||||
sumLogImpl[i].clear();
|
||||
sumSqImpl[i].clear();
|
||||
geoMeanImpl[i].clear();
|
||||
meanImpl[i].clear();
|
||||
}
|
||||
covarianceImpl.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff <code>object</code> is a <code>SummaryStatistics</code>
|
||||
* instance and all statistics have the same values as this.
|
||||
* @param object the object to test equality against.
|
||||
* @return true if object equals this
|
||||
*/
|
||||
public boolean equals(Object object) {
|
||||
if (object == this ) {
|
||||
return true;
|
||||
}
|
||||
if (object instanceof MultivariateSummaryStatistics == false) {
|
||||
return false;
|
||||
}
|
||||
MultivariateSummaryStatistics stat = (MultivariateSummaryStatistics) object;
|
||||
return (MathUtils.equals(stat.getGeometricMean(),
|
||||
this.getGeometricMean()) &&
|
||||
MathUtils.equals(stat.getMax(), this.getMax()) &&
|
||||
MathUtils.equals(stat.getMean(),this.getMean()) &&
|
||||
MathUtils.equals(stat.getMin(),this.getMin()) &&
|
||||
MathUtils.equals(stat.getN(), this.getN()) &&
|
||||
MathUtils.equals(stat.getSum(), this.getSum()) &&
|
||||
MathUtils.equals(stat.getSumSq(),this.getSumSq()) &&
|
||||
MathUtils.equals(stat.getSumLog(),this.getSumLog()) &&
|
||||
stat.getCovariance().equals(this.getCovariance()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hash code based on values of statistics
|
||||
*
|
||||
* @return hash code
|
||||
*/
|
||||
public int hashCode() {
|
||||
int result = 31 + MathUtils.hash(getGeometricMean());
|
||||
result = result * 31 + MathUtils.hash(getGeometricMean());
|
||||
result = result * 31 + MathUtils.hash(getMax());
|
||||
result = result * 31 + MathUtils.hash(getMean());
|
||||
result = result * 31 + MathUtils.hash(getMin());
|
||||
result = result * 31 + MathUtils.hash(getN());
|
||||
result = result * 31 + MathUtils.hash(getSum());
|
||||
result = result * 31 + MathUtils.hash(getSumSq());
|
||||
result = result * 31 + MathUtils.hash(getSumLog());
|
||||
result = result * 31 + getCovariance().hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Getters and setters for statistics implementations
|
||||
/**
|
||||
* Returns the currently configured Sum implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the sum
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getSumImpl() {
|
||||
return sumImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the Sum.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param sumImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the Sum
|
||||
* @throws IllegalArgumentException if the array dimension
|
||||
* does not match the one used at construction
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setSumImpl(StorelessUnivariateStatistic[] sumImpl) {
|
||||
checkEmpty();
|
||||
this.sumImpl = sumImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently configured sum of squares implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the sum of squares
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getSumsqImpl() {
|
||||
return sumSqImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the sum of squares.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param sumsqImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the sum of squares
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setSumsqImpl(StorelessUnivariateStatistic[] sumsqImpl) {
|
||||
checkEmpty();
|
||||
this.sumSqImpl = sumsqImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently configured minimum implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the minimum
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getMinImpl() {
|
||||
return minImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the minimum.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param minImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the minimum
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setMinImpl(StorelessUnivariateStatistic[] minImpl) {
|
||||
checkEmpty();
|
||||
this.minImpl = minImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently configured maximum implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the maximum
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getMaxImpl() {
|
||||
return maxImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the maximum.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param maxImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the maximum
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setMaxImpl(StorelessUnivariateStatistic[] maxImpl) {
|
||||
checkEmpty();
|
||||
this.maxImpl = maxImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently configured sum of logs implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the log sum
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getSumLogImpl() {
|
||||
return sumLogImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the sum of logs.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param sumLogImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the log sum
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setSumLogImpl(StorelessUnivariateStatistic[] sumLogImpl) {
|
||||
checkEmpty();
|
||||
this.sumLogImpl = sumLogImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently configured geometric mean implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the geometric mean
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getGeoMeanImpl() {
|
||||
return geoMeanImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the geometric mean.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param geoMeanImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the geometric mean
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setGeoMeanImpl(StorelessUnivariateStatistic[] geoMeanImpl) {
|
||||
checkEmpty();
|
||||
this.geoMeanImpl = geoMeanImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently configured mean implementation
|
||||
*
|
||||
* @return the StorelessUnivariateStatistic implementing the mean
|
||||
*/
|
||||
public StorelessUnivariateStatistic[] getMeanImpl() {
|
||||
return meanImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the implementation for the mean.</p>
|
||||
* <p>This method must be activated before any data has been added - i.e.,
|
||||
* before {@link #addValue(double[]) addValue} has been used to add data;
|
||||
* otherwise an IllegalStateException will be thrown.</p>
|
||||
*
|
||||
* @param meanImpl the StorelessUnivariateStatistic instance to use
|
||||
* for computing the mean
|
||||
* @throws IllegalStateException if data has already been added
|
||||
* (i.e if n > 0)
|
||||
*/
|
||||
public void setMeanImpl(StorelessUnivariateStatistic[] meanImpl) {
|
||||
checkEmpty();
|
||||
this.meanImpl = meanImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws IllegalStateException if n > 0.
|
||||
*/
|
||||
private void checkEmpty() {
|
||||
if (n > 0) {
|
||||
throw new IllegalStateException(
|
||||
"Implementations must be configured before values are added.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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 org.apache.commons.math.linear.RealMatrix;
|
||||
|
||||
/**
|
||||
* Reporting interface for basic multivariate statistics.
|
||||
*
|
||||
* @since 1.2
|
||||
* @version $Revision: 480440 $ $Date: 2006-11-29 08:14:12 +0100 (mer., 29 nov. 2006) $
|
||||
*/
|
||||
public interface StatisticalMultivariateSummary {
|
||||
/**
|
||||
* Returns the dimension of the data
|
||||
* @return The dimension of the data
|
||||
*/
|
||||
public int getDimension();
|
||||
/**
|
||||
* Returns the <a href="http://www.xycoon.com/arithmetic_mean.htm">
|
||||
* arithmetic mean </a> of the available values
|
||||
* @return The mean or null if no values have been added.
|
||||
*/
|
||||
public abstract double[] getMean();
|
||||
/**
|
||||
* Returns the covariance of the available values.
|
||||
* @return The covariance, null if no values have been added
|
||||
* or a zeroed matrix for a single value set.
|
||||
*/
|
||||
public abstract RealMatrix getCovariance();
|
||||
/**
|
||||
* Returns the standard deviation of the available values.
|
||||
* @return The standard deviation, null if no values have been added
|
||||
* or a zeroed array for a single value set.
|
||||
*/
|
||||
public abstract double[] getStandardDeviation();
|
||||
/**
|
||||
* Returns the maximum of the available values
|
||||
* @return The max or null if no values have been added.
|
||||
*/
|
||||
public abstract double[] getMax();
|
||||
/**
|
||||
* Returns the minimum of the available values
|
||||
* @return The min or null if no values have been added.
|
||||
*/
|
||||
public abstract double[] getMin();
|
||||
/**
|
||||
* Returns the number of available values
|
||||
* @return The number of available values
|
||||
*/
|
||||
public abstract long getN();
|
||||
/**
|
||||
* Returns the sum of the values that have been added.
|
||||
* @return The sum or null if no values have been added
|
||||
*/
|
||||
public abstract double[] getSum();
|
||||
/**
|
||||
* Returns the sum of the squares of the values that have been added.
|
||||
* @return The sum or null if no values have been added
|
||||
*/
|
||||
public abstract double[] getSumSq();
|
||||
/**
|
||||
* Returns the sum of the logarithms of the values that have been added.
|
||||
* @return The sum or null if no values have been added
|
||||
*/
|
||||
public abstract double[] getSumLog();
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.math.linear.RealMatrix;
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
* Value object representing the results of a statistical multivariate summary.
|
||||
*
|
||||
* @since 1.2
|
||||
* @version $Revision: 480440 $ $Date: 2006-11-29 08:14:12 +0100 (mer., 29 nov. 2006) $
|
||||
*/
|
||||
public class StatisticalMultivariateSummaryValues
|
||||
implements Serializable, StatisticalMultivariateSummary {
|
||||
|
||||
/** Serialization id */
|
||||
private static final long serialVersionUID = 8152538650791979064L;
|
||||
|
||||
/** Dimension of the data. */
|
||||
private final int k;
|
||||
|
||||
/** The sample mean */
|
||||
private final double[] mean;
|
||||
|
||||
/** The sample covariance */
|
||||
private final RealMatrix covariance;
|
||||
|
||||
/** The sample standard deviation. */
|
||||
private double[] stdev;
|
||||
|
||||
/** The number of observations in the sample */
|
||||
private final long n;
|
||||
|
||||
/** The maximum value */
|
||||
private final double[] max;
|
||||
|
||||
/** The minimum value */
|
||||
private final double[] min;
|
||||
|
||||
/** The sum of the sample values */
|
||||
private final double[] sum;
|
||||
|
||||
/** The sum of the squares of the sample values */
|
||||
private final double[] sumSq;
|
||||
|
||||
/** The sum of the logarithms of the sample values */
|
||||
private final double[] sumLog;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param mean the sample mean
|
||||
* @param covariance the sample covariance
|
||||
* @param stdev the sample standard deviation
|
||||
* @param k dimension of the data
|
||||
* @param n the number of observations in the sample
|
||||
* @param max the maximum value
|
||||
* @param min the minimum value
|
||||
* @param sum the sum of the values
|
||||
* @param sumSq the sum of the squares of the values
|
||||
* @param sumLog the sum of the logarithms of the values
|
||||
*/
|
||||
public StatisticalMultivariateSummaryValues(int k, double[] mean,
|
||||
RealMatrix covariance, double[] stdev,
|
||||
long n, double[] max, double[] min,
|
||||
double[] sum, double[] sumSq, double[] sumLog) {
|
||||
super();
|
||||
this.k = k;
|
||||
this.mean = mean;
|
||||
this.covariance = covariance;
|
||||
this.stdev = stdev;
|
||||
this.n = n;
|
||||
this.max = max;
|
||||
this.min = min;
|
||||
this.sum = sum;
|
||||
this.sumSq = sumSq;
|
||||
this.sumLog = sumLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimension of the data
|
||||
* @return The dimension of the data
|
||||
*/
|
||||
public int getDimension() {
|
||||
return k;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the max.
|
||||
*/
|
||||
public double[] getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the mean.
|
||||
*/
|
||||
public double[] getMean() {
|
||||
return mean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the min.
|
||||
*/
|
||||
public double[] getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the number of values.
|
||||
*/
|
||||
public long getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the sum.
|
||||
*/
|
||||
public double[] getSum() {
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the sum of the squares.
|
||||
*/
|
||||
public double[] getSumSq() {
|
||||
return sumSq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the sum of the logarithms.
|
||||
*/
|
||||
public double[] getSumLog() {
|
||||
return sumLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the standard deviation (roots of the diagonal elements)
|
||||
*/
|
||||
public double[] getStandardDeviation() {
|
||||
return stdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the covariance.
|
||||
*/
|
||||
public RealMatrix getCovariance() {
|
||||
return covariance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff <code>object</code> is a
|
||||
* <code>StatisticalSummaryValues</code> instance and all statistics have
|
||||
* the same values as this.
|
||||
*
|
||||
* @param object the object to test equality against.
|
||||
* @return true if object equals this
|
||||
*/
|
||||
public boolean equals(Object object) {
|
||||
if (object == this ) {
|
||||
return true;
|
||||
}
|
||||
if (object instanceof StatisticalMultivariateSummaryValues == false) {
|
||||
return false;
|
||||
}
|
||||
StatisticalMultivariateSummaryValues stat = (StatisticalMultivariateSummaryValues) object;
|
||||
return ((stat.getDimension() == this.getDimension()) &&
|
||||
MathUtils.equals(stat.getMax(), this.getMax()) &&
|
||||
MathUtils.equals(stat.getMean(),this.getMean()) &&
|
||||
MathUtils.equals(stat.getMin(),this.getMin()) &&
|
||||
MathUtils.equals(stat.getN(), this.getN()) &&
|
||||
MathUtils.equals(stat.getSum(), this.getSum()) &&
|
||||
MathUtils.equals(stat.getSumSq(), this.getSumSq()) &&
|
||||
MathUtils.equals(stat.getSumLog(), this.getSumLog()) &&
|
||||
MathUtils.equals(stat.getStandardDeviation(), this.getStandardDeviation()) &&
|
||||
stat.getCovariance().equals(this.getCovariance()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hash code based on values of statistics
|
||||
*
|
||||
* @return hash code
|
||||
*/
|
||||
public int hashCode() {
|
||||
int result = getDimension();
|
||||
result = result * 31 + MathUtils.hash(getMax());
|
||||
result = result * 31 + MathUtils.hash(getMean());
|
||||
result = result * 31 + MathUtils.hash(getMin());
|
||||
result = result * 31 + MathUtils.hash(getN());
|
||||
result = result * 31 + MathUtils.hash(getSum());
|
||||
result = result * 31 + MathUtils.hash(getSumSq());
|
||||
result = result * 31 + MathUtils.hash(getSumLog());
|
||||
result = result * 31 + getCovariance().hashCode();
|
||||
result = result * 31 + MathUtils.hash(getStandardDeviation());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* 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 org.apache.commons.math.DimensionMismatchException;
|
||||
import org.apache.commons.math.linear.RealMatrix;
|
||||
|
||||
/**
|
||||
* Implementation of
|
||||
* {@link org.apache.commons.math.stat.descriptive.MultivariateSummaryStatistics} that
|
||||
* is safe to use in a multithreaded environment. Multiple threads can safely
|
||||
* operate on a single instance without causing runtime exceptions due to race
|
||||
* conditions. In effect, this implementation makes modification and access
|
||||
* methods atomic operations for a single instance. That is to say, as one
|
||||
* thread is computing a statistic from the instance, no other thread can modify
|
||||
* the instance nor compute another statistic.
|
||||
* @since 1.2
|
||||
* @version $Revision: 618097 $ $Date: 2008-02-03 22:39:08 +0100 (dim., 03 févr. 2008) $
|
||||
*/
|
||||
public class SynchronizedMultivariateSummaryStatistics
|
||||
extends MultivariateSummaryStatistics {
|
||||
|
||||
/** Serialization UID */
|
||||
private static final long serialVersionUID = 7099834153347155363L;
|
||||
|
||||
/**
|
||||
* Construct a SynchronizedMultivariateSummaryStatistics instance
|
||||
* @param k dimension of the data
|
||||
* @param isCovarianceBiasCorrected if true, the unbiased sample
|
||||
* covariance is computed, otherwise the biased population covariance
|
||||
* is computed
|
||||
*/
|
||||
public SynchronizedMultivariateSummaryStatistics(int k, boolean isCovarianceBiasCorrected) {
|
||||
super(k, isCovarianceBiasCorrected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSummary()
|
||||
*/
|
||||
public synchronized StatisticalMultivariateSummary getSummary() {
|
||||
return super.getSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#addValue(double[])
|
||||
*/
|
||||
public synchronized void addValue(double[] value)
|
||||
throws DimensionMismatchException {
|
||||
super.addValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getDimension()
|
||||
*/
|
||||
public synchronized int getDimension() {
|
||||
return super.getDimension();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getN()
|
||||
*/
|
||||
public synchronized long getN() {
|
||||
return super.getN();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSum()
|
||||
*/
|
||||
public synchronized double[] getSum() {
|
||||
return super.getSum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSummSq()
|
||||
*/
|
||||
public synchronized double[] getSumSq() {
|
||||
return super.getSumSq();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSumLog()
|
||||
*/
|
||||
public synchronized double[] getSumLog() {
|
||||
return super.getSumLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getMean()
|
||||
*/
|
||||
public synchronized double[] getMean() {
|
||||
return super.getMean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getStandardDeviation()
|
||||
*/
|
||||
public synchronized double[] getStandardDeviation() {
|
||||
return super.getStandardDeviation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getCovariance()
|
||||
*/
|
||||
public synchronized RealMatrix getCovariance() {
|
||||
return super.getCovariance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getMax()
|
||||
*/
|
||||
public synchronized double[] getMax() {
|
||||
return super.getMax();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getMin()
|
||||
*/
|
||||
public synchronized double[] getMin() {
|
||||
return super.getMin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getGeometricMean()
|
||||
*/
|
||||
public synchronized double[] getGeometricMean() {
|
||||
return super.getGeometricMean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#toString()
|
||||
*/
|
||||
public synchronized String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#clear()
|
||||
*/
|
||||
public synchronized void clear() {
|
||||
super.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#equals()
|
||||
*/
|
||||
public synchronized boolean equals(Object object) {
|
||||
return super.equals(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#hashCode()
|
||||
*/
|
||||
public synchronized int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSumImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getSumImpl() {
|
||||
return super.getSumImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setSumImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setSumImpl(StorelessUnivariateStatistic[] sumImpl) {
|
||||
super.setSumImpl(sumImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSumsqImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getSumsqImpl() {
|
||||
return super.getSumsqImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setSumsqImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setSumsqImpl(StorelessUnivariateStatistic[] sumsqImpl) {
|
||||
super.setSumsqImpl(sumsqImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getMinImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getMinImpl() {
|
||||
return super.getMinImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setMinImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setMinImpl(StorelessUnivariateStatistic[] minImpl) {
|
||||
super.setMinImpl(minImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getMaxImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getMaxImpl() {
|
||||
return super.getMaxImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setMaxImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setMaxImpl(StorelessUnivariateStatistic[] maxImpl) {
|
||||
super.setMaxImpl(maxImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getSumLogImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getSumLogImpl() {
|
||||
return super.getSumLogImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setSumLogImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setSumLogImpl(StorelessUnivariateStatistic[] sumLogImpl) {
|
||||
super.setSumLogImpl(sumLogImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getGeoMeanImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getGeoMeanImpl() {
|
||||
return super.getGeoMeanImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setGeoMeanImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setGeoMeanImpl(StorelessUnivariateStatistic[] geoMeanImpl) {
|
||||
super.setGeoMeanImpl(geoMeanImpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#getMeanImpl()
|
||||
*/
|
||||
public synchronized StorelessUnivariateStatistic[] getMeanImpl() {
|
||||
return super.getMeanImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.commons.math.stat.descriptive.MultivariateSummary#setMeanImpl(StorelessUnivariateStatistic[])
|
||||
*/
|
||||
public synchronized void setMeanImpl(StorelessUnivariateStatistic[] meanImpl) {
|
||||
super.setMeanImpl(meanImpl);
|
||||
}
|
||||
|
||||
}
|
|
@ -154,6 +154,9 @@ Commons Math Release Notes</title>
|
|||
Added vectorial covariance computation (either sample or population
|
||||
covariance)
|
||||
</action>
|
||||
<action dev="luc" type="update" >
|
||||
Added multivariate summary statistics
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.1" date="2005-12-17"
|
||||
description="This is a maintenance release containing bug fixes and enhancements.
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.math.DimensionMismatchException;
|
||||
import org.apache.commons.math.TestUtils;
|
||||
import org.apache.commons.math.stat.descriptive.moment.Mean;
|
||||
|
||||
/**
|
||||
* Test cases for the {@link MultivariateSummaryStatistics} class.
|
||||
*
|
||||
* @version $Revision: 566833 $ $Date: 2007-08-16 13:36:33 -0700 (Thu, 16 Aug 2007) $
|
||||
*/
|
||||
|
||||
public class MultivariateSummaryStatisticsTest extends TestCase {
|
||||
|
||||
public MultivariateSummaryStatisticsTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite(MultivariateSummaryStatisticsTest.class);
|
||||
suite.setName("MultivariateSummaryStatistics tests");
|
||||
return suite;
|
||||
}
|
||||
|
||||
public void testSetterInjection() throws Exception {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
|
||||
u.setMeanImpl(new StorelessUnivariateStatistic[] {
|
||||
new sumMean(), new sumMean()
|
||||
});
|
||||
u.addValue(new double[] { 1, 2 });
|
||||
u.addValue(new double[] { 3, 4 });
|
||||
assertEquals(4, u.getMean()[0], 1E-14);
|
||||
assertEquals(6, u.getMean()[1], 1E-14);
|
||||
u.clear();
|
||||
u.addValue(new double[] { 1, 2 });
|
||||
u.addValue(new double[] { 3, 4 });
|
||||
assertEquals(4, u.getMean()[0], 1E-14);
|
||||
assertEquals(6, u.getMean()[1], 1E-14);
|
||||
u.clear();
|
||||
u.setMeanImpl(new StorelessUnivariateStatistic[] {
|
||||
new Mean(), new Mean()
|
||||
}); // OK after clear
|
||||
u.addValue(new double[] { 1, 2 });
|
||||
u.addValue(new double[] { 3, 4 });
|
||||
assertEquals(2, u.getMean()[0], 1E-14);
|
||||
assertEquals(3, u.getMean()[1], 1E-14);
|
||||
}
|
||||
|
||||
public void testSetterIllegalState() throws Exception {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
|
||||
u.addValue(new double[] { 1, 2 });
|
||||
u.addValue(new double[] { 3, 4 });
|
||||
try {
|
||||
u.setMeanImpl(new StorelessUnivariateStatistic[] {
|
||||
new sumMean(), new sumMean()
|
||||
});
|
||||
fail("Expecting IllegalStateException");
|
||||
} catch (IllegalStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bogus mean implementation to test setter injection.
|
||||
* Returns the sum instead of the mean.
|
||||
*/
|
||||
static class sumMean implements StorelessUnivariateStatistic {
|
||||
private static final long serialVersionUID = 6492471391340853423L;
|
||||
private double sum = 0;
|
||||
private long n = 0;
|
||||
public double evaluate(double[] values, int begin, int length) {
|
||||
return 0;
|
||||
}
|
||||
public double evaluate(double[] values) {
|
||||
return 0;
|
||||
}
|
||||
public void clear() {
|
||||
sum = 0;
|
||||
n = 0;
|
||||
}
|
||||
public long getN() {
|
||||
return n;
|
||||
}
|
||||
public double getResult() {
|
||||
return sum;
|
||||
}
|
||||
public void increment(double d) {
|
||||
sum += d;
|
||||
n++;
|
||||
}
|
||||
public void incrementAll(double[] values, int start, int length) {
|
||||
}
|
||||
public void incrementAll(double[] values) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testDimension() {
|
||||
try {
|
||||
new MultivariateSummaryStatistics(2, true).addValue(new double[3]);
|
||||
} catch (DimensionMismatchException dme) {
|
||||
// expected behavior
|
||||
} catch (Exception e) {
|
||||
fail("wrong exception caught");
|
||||
}
|
||||
}
|
||||
|
||||
/** test stats */
|
||||
public void testStats() throws DimensionMismatchException {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
|
||||
assertEquals(0, u.getN());
|
||||
u.addValue(new double[] { 1, 2 });
|
||||
u.addValue(new double[] { 2, 3 });
|
||||
u.addValue(new double[] { 2, 3 });
|
||||
u.addValue(new double[] { 3, 4 });
|
||||
assertEquals( 4, u.getN());
|
||||
assertEquals( 8, u.getSum()[0], 1.0e-10);
|
||||
assertEquals(12, u.getSum()[1], 1.0e-10);
|
||||
assertEquals(18, u.getSumSq()[0], 1.0e-10);
|
||||
assertEquals(38, u.getSumSq()[1], 1.0e-10);
|
||||
assertEquals( 1, u.getMin()[0], 1.0e-10);
|
||||
assertEquals( 2, u.getMin()[1], 1.0e-10);
|
||||
assertEquals( 3, u.getMax()[0], 1.0e-10);
|
||||
assertEquals( 4, u.getMax()[1], 1.0e-10);
|
||||
assertEquals(2.4849066497880003102, u.getSumLog()[0], 1.0e-10);
|
||||
assertEquals( 4.276666119016055311, u.getSumLog()[1], 1.0e-10);
|
||||
assertEquals( 1.8612097182041991979, u.getGeometricMean()[0], 1.0e-10);
|
||||
assertEquals( 2.9129506302439405217, u.getGeometricMean()[1], 1.0e-10);
|
||||
assertEquals( 2, u.getMean()[0], 1.0e-10);
|
||||
assertEquals( 3, u.getMean()[1], 1.0e-10);
|
||||
assertEquals(Math.sqrt(2.0 / 3.0), u.getStandardDeviation()[0], 1.0e-10);
|
||||
assertEquals(Math.sqrt(2.0 / 3.0), u.getStandardDeviation()[1], 1.0e-10);
|
||||
assertEquals(2.0 / 3.0, u.getCovariance().getEntry(0, 0), 1.0e-10);
|
||||
assertEquals(2.0 / 3.0, u.getCovariance().getEntry(0, 1), 1.0e-10);
|
||||
assertEquals(2.0 / 3.0, u.getCovariance().getEntry(1, 0), 1.0e-10);
|
||||
assertEquals(2.0 / 3.0, u.getCovariance().getEntry(1, 1), 1.0e-10);
|
||||
u.clear();
|
||||
assertEquals(0, u.getN());
|
||||
}
|
||||
|
||||
public void testN0andN1Conditions() throws Exception {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(1, true);
|
||||
assertTrue(Double.isNaN(u.getMean()[0]));
|
||||
assertTrue(Double.isNaN(u.getStandardDeviation()[0]));
|
||||
|
||||
/* n=1 */
|
||||
u.addValue(new double[] { 1 });
|
||||
assertEquals(1.0, u.getMean()[0], 1.0e-10);
|
||||
assertEquals(1.0, u.getGeometricMean()[0], 1.0e-10);
|
||||
assertEquals(0.0, u.getStandardDeviation()[0], 1.0e-10);
|
||||
|
||||
/* n=2 */
|
||||
u.addValue(new double[] { 2 });
|
||||
assertTrue(u.getStandardDeviation()[0] > 0);
|
||||
|
||||
}
|
||||
|
||||
public void testNaNContracts() throws DimensionMismatchException {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(1, true);
|
||||
assertTrue(Double.isNaN(u.getMean()[0]));
|
||||
assertTrue(Double.isNaN(u.getMin()[0]));
|
||||
assertTrue(Double.isNaN(u.getStandardDeviation()[0]));
|
||||
assertTrue(Double.isNaN(u.getGeometricMean()[0]));
|
||||
|
||||
u.addValue(new double[] { 1.0 });
|
||||
assertFalse(Double.isNaN(u.getMean()[0]));
|
||||
assertFalse(Double.isNaN(u.getMin()[0]));
|
||||
assertFalse(Double.isNaN(u.getStandardDeviation()[0]));
|
||||
assertFalse(Double.isNaN(u.getGeometricMean()[0]));
|
||||
|
||||
}
|
||||
|
||||
public void testGetSummary() throws DimensionMismatchException {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
|
||||
StatisticalMultivariateSummary summary = u.getSummary();
|
||||
verifySummary(u, summary);
|
||||
u.addValue(new double[] { 1, 2 });
|
||||
summary = u.getSummary();
|
||||
verifySummary(u, summary);
|
||||
u.addValue(new double[] { 2, 5 });
|
||||
summary = u.getSummary();
|
||||
verifySummary(u, summary);
|
||||
u.addValue(new double[] { 2, 2 });
|
||||
summary = u.getSummary();
|
||||
verifySummary(u, summary);
|
||||
}
|
||||
|
||||
public void testSerialization() throws DimensionMismatchException {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
|
||||
// Empty test
|
||||
TestUtils.checkSerializedEquality(u);
|
||||
MultivariateSummaryStatistics s = (MultivariateSummaryStatistics) TestUtils.serializeAndRecover(u);
|
||||
StatisticalMultivariateSummary summary = s.getSummary();
|
||||
verifySummary(u, summary);
|
||||
|
||||
// Add some data
|
||||
u.addValue(new double[] { 2d, 1d });
|
||||
u.addValue(new double[] { 1d, 1d });
|
||||
u.addValue(new double[] { 3d, 1d });
|
||||
u.addValue(new double[] { 4d, 1d });
|
||||
u.addValue(new double[] { 5d, 1d });
|
||||
|
||||
// Test again
|
||||
TestUtils.checkSerializedEquality(u);
|
||||
s = (MultivariateSummaryStatistics) TestUtils.serializeAndRecover(u);
|
||||
summary = s.getSummary();
|
||||
verifySummary(u, summary);
|
||||
|
||||
}
|
||||
|
||||
public void testEqualsAndHashCode() throws DimensionMismatchException {
|
||||
MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
|
||||
MultivariateSummaryStatistics t = null;
|
||||
int emptyHash = u.hashCode();
|
||||
assertTrue(u.equals(u));
|
||||
assertFalse(u.equals(t));
|
||||
assertFalse(u.equals(new Double(0)));
|
||||
t = new MultivariateSummaryStatistics(2, true);
|
||||
assertTrue(t.equals(u));
|
||||
assertTrue(u.equals(t));
|
||||
assertEquals(emptyHash, t.hashCode());
|
||||
|
||||
// Add some data to u
|
||||
u.addValue(new double[] { 2d, 1d });
|
||||
u.addValue(new double[] { 1d, 1d });
|
||||
u.addValue(new double[] { 3d, 1d });
|
||||
u.addValue(new double[] { 4d, 1d });
|
||||
u.addValue(new double[] { 5d, 1d });
|
||||
assertFalse(t.equals(u));
|
||||
assertFalse(u.equals(t));
|
||||
assertTrue(u.hashCode() != t.hashCode());
|
||||
|
||||
//Add data in same order to t
|
||||
t.addValue(new double[] { 2d, 1d });
|
||||
t.addValue(new double[] { 1d, 1d });
|
||||
t.addValue(new double[] { 3d, 1d });
|
||||
t.addValue(new double[] { 4d, 1d });
|
||||
t.addValue(new double[] { 5d, 1d });
|
||||
assertTrue(t.equals(u));
|
||||
assertTrue(u.equals(t));
|
||||
assertEquals(u.hashCode(), t.hashCode());
|
||||
|
||||
// Clear and make sure summaries are indistinguishable from empty summary
|
||||
u.clear();
|
||||
t.clear();
|
||||
assertTrue(t.equals(u));
|
||||
assertTrue(u.equals(t));
|
||||
assertEquals(emptyHash, t.hashCode());
|
||||
assertEquals(emptyHash, u.hashCode());
|
||||
}
|
||||
|
||||
private void verifySummary(MultivariateSummaryStatistics u, StatisticalMultivariateSummary s) {
|
||||
assertEquals(s.getN(), u.getN());
|
||||
for (int i = 0; i < u.getDimension(); ++i) {
|
||||
checkValue(s.getSum()[i], u.getSum()[i], 1.0e-10);
|
||||
checkValue(s.getStandardDeviation()[i], u.getStandardDeviation()[i], 1.0e-10);
|
||||
checkValue(s.getMean()[i], u.getMean()[i], 1.0e-10);
|
||||
checkValue(s.getMin()[i], u.getMin()[i], 1.0e-10);
|
||||
checkValue(s.getMax()[i], u.getMax()[i], 1.0e-10);
|
||||
checkValue(s.getSumSq()[i], u.getSumSq()[i], 1.0e-10);
|
||||
checkValue(s.getSumLog()[i], u.getSumLog()[i], 1.0e-10);
|
||||
checkValue(s.getMax()[i], u.getMax()[i], 1.0e-10);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkValue(double expected, double actual, double tolerance) {
|
||||
if (Double.isNaN(expected)) {
|
||||
assertTrue(Double.isNaN(actual));
|
||||
} else {
|
||||
assertEquals(expected, actual, tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue