001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.stat.descriptive.moment; 018 019 import java.io.Serializable; 020 021 import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic; 022 import org.apache.commons.math.stat.descriptive.summary.Sum; 023 024 /** 025 * <p>Computes the arithmetic mean of a set of values. Uses the definitional 026 * formula:</p> 027 * <p> 028 * mean = sum(x_i) / n 029 * </p> 030 * <p>where <code>n</code> is the number of observations. 031 * </p> 032 * <p>When {@link #increment(double)} is used to add data incrementally from a 033 * stream of (unstored) values, the value of the statistic that 034 * {@link #getResult()} returns is computed using the following recursive 035 * updating algorithm: </p> 036 * <ol> 037 * <li>Initialize <code>m = </code> the first value</li> 038 * <li>For each additional value, update using <br> 039 * <code>m = m + (new value - m) / (number of observations)</code></li> 040 * </ol> 041 * <p> If {@link #evaluate(double[])} is used to compute the mean of an array 042 * of stored values, a two-pass, corrected algorithm is used, starting with 043 * the definitional formula computed using the array of stored values and then 044 * correcting this by adding the mean deviation of the data values from the 045 * arithmetic mean. See, e.g. "Comparison of Several Algorithms for Computing 046 * Sample Means and Variances," Robert F. Ling, Journal of the American 047 * Statistical Association, Vol. 69, No. 348 (Dec., 1974), pp. 859-866. </p> 048 * <p> 049 * Returns <code>Double.NaN</code> if the dataset is empty. 050 * </p> 051 * <strong>Note that this implementation is not synchronized.</strong> If 052 * multiple threads access an instance of this class concurrently, and at least 053 * one of the threads invokes the <code>increment()</code> or 054 * <code>clear()</code> method, it must be synchronized externally. 055 * 056 * @version $Revision: 762116 $ $Date: 2009-04-05 12:48:53 -0400 (Sun, 05 Apr 2009) $ 057 */ 058 public class Mean extends AbstractStorelessUnivariateStatistic 059 implements Serializable { 060 061 /** Serializable version identifier */ 062 private static final long serialVersionUID = -1296043746617791564L; 063 064 /** First moment on which this statistic is based. */ 065 protected FirstMoment moment; 066 067 /** 068 * Determines whether or not this statistic can be incremented or cleared. 069 * <p> 070 * Statistics based on (constructed from) external moments cannot 071 * be incremented or cleared.</p> 072 */ 073 protected boolean incMoment; 074 075 /** Constructs a Mean. */ 076 public Mean() { 077 incMoment = true; 078 moment = new FirstMoment(); 079 } 080 081 /** 082 * Constructs a Mean with an External Moment. 083 * 084 * @param m1 the moment 085 */ 086 public Mean(final FirstMoment m1) { 087 this.moment = m1; 088 incMoment = false; 089 } 090 091 /** 092 * Copy constructor, creates a new {@code Mean} identical 093 * to the {@code original} 094 * 095 * @param original the {@code Mean} instance to copy 096 */ 097 public Mean(Mean original) { 098 copy(original, this); 099 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override 105 public void increment(final double d) { 106 if (incMoment) { 107 moment.increment(d); 108 } 109 } 110 111 /** 112 * {@inheritDoc} 113 */ 114 @Override 115 public void clear() { 116 if (incMoment) { 117 moment.clear(); 118 } 119 } 120 121 /** 122 * {@inheritDoc} 123 */ 124 @Override 125 public double getResult() { 126 return moment.m1; 127 } 128 129 /** 130 * {@inheritDoc} 131 */ 132 public long getN() { 133 return moment.getN(); 134 } 135 136 /** 137 * Returns the arithmetic mean of the entries in the specified portion of 138 * the input array, or <code>Double.NaN</code> if the designated subarray 139 * is empty. 140 * <p> 141 * Throws <code>IllegalArgumentException</code> if the array is null.</p> 142 * <p> 143 * See {@link Mean} for details on the computing algorithm.</p> 144 * 145 * @param values the input array 146 * @param begin index of the first array element to include 147 * @param length the number of elements to include 148 * @return the mean of the values or Double.NaN if length = 0 149 * @throws IllegalArgumentException if the array is null or the array index 150 * parameters are not valid 151 */ 152 @Override 153 public double evaluate(final double[] values,final int begin, final int length) { 154 if (test(values, begin, length)) { 155 Sum sum = new Sum(); 156 double sampleSize = length; 157 158 // Compute initial estimate using definitional formula 159 double xbar = sum.evaluate(values, begin, length) / sampleSize; 160 161 // Compute correction factor in second pass 162 double correction = 0; 163 for (int i = begin; i < begin + length; i++) { 164 correction += (values[i] - xbar); 165 } 166 return xbar + (correction/sampleSize); 167 } 168 return Double.NaN; 169 } 170 171 /** 172 * {@inheritDoc} 173 */ 174 @Override 175 public Mean copy() { 176 Mean result = new Mean(); 177 copy(this, result); 178 return result; 179 } 180 181 182 /** 183 * Copies source to dest. 184 * <p>Neither source nor dest can be null.</p> 185 * 186 * @param source Mean to copy 187 * @param dest Mean to copy to 188 * @throws NullPointerException if either source or dest is null 189 */ 190 public static void copy(Mean source, Mean dest) { 191 dest.incMoment = source.incMoment; 192 dest.moment = source.moment.copy(); 193 } 194 }