Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/statistics.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2011 Eric Nichols <epnichols@gmail.com>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 
00020 #include "statistics.h"
00021 #include <algorithm>
00022 
00023 using std::ostringstream;
00024 using std::numeric_limits;
00025 using std::endl;
00026 using std::cout;
00027 using std::cerr;
00028 using std::min;
00029 using std::max;
00030 
00031 
00032 using namespace Marsyas;
00033 
00034 statistics::statistics()
00035 {
00036 }
00037 
00038 statistics::~statistics()
00039 {
00040 }
00041 
00042 // PRIVATE
00043 
00044 // Returns the nth moment about the mean for data that's already been converted to z-scores.
00045 mrs_real
00046 statistics::momentN(const realvec& zData, const realvec& weights, int n)
00047 {
00048   if (zData.getSize() != weights.getSize())
00049   {
00050     MRSERR("statistics::momentN - wrong size for weights vector!");
00051     return -1.0;
00052   }
00053 
00054   mrs_real sum = 0.0;
00055 
00056   for (mrs_natural i=0; i < zData.getSize(); i++)
00057   {
00058     sum += weights(i) * pow(zData(i), n);
00059   }
00060 
00061   return sum;
00062 }
00063 
00064 
00065 // Computes z scores for a set of data, given a mean.
00066 // The mean is needed so that this fxn can be used to compute moments about 0
00067 // (instead of about the actual mean).
00068 realvec
00069 statistics::zDataWeighted(const realvec& data, const realvec& weights, mrs_real mean)
00070 {
00071   realvec zData;
00072   zData.create(data.getSize());
00073 
00074   if (data.getSize() != weights.getSize())
00075   {
00076     MRSERR("statistics::zDataWeighted - wrong size for weights vector!");
00077     return zData;
00078   }
00079 
00080   mrs_real sd = statistics::stddevWeighted(data, weights, mean);
00081 
00082   if (sd == 0)
00083   {
00084     MRSWARN("statistics::zDataWeighted - standard deviation is 0.");
00085     return zData;
00086   }
00087 
00088   for (mrs_natural i=0; i < zData.getSize(); i++)
00089     zData(i) = (data(i) - mean) / sd;
00090 
00091   return zData;
00092 }
00093 
00094 
00095 
00096 // PUBLIC
00097 
00098 
00099 // Computes the mean for a vector where each element has an
00100 // associated weight (i.e. computes the weighted mean).
00101 mrs_real
00102 statistics::meanWeighted(const realvec& data, const realvec& weights)
00103 {
00104   if (data.getSize() != weights.getSize())
00105   {
00106     MRSERR("statistics::meanWeighted - wrong size for weights vector!");
00107     return -1.0;
00108   }
00109 
00110   mrs_real sum = 0.0;
00111   mrs_real weightsSum = 0.0;
00112 
00113   for (mrs_natural i=0; i < data.getSize(); i++)
00114   {
00115     mrs_real w = weights(i);
00116 
00117     sum += w * data(i);
00118     weightsSum += w;
00119   }
00120 
00121   if (weightsSum != 0.0) sum /= weightsSum;
00122   return sum;
00123 }
00124 
00125 
00126 // Computes the standard deviation for a vector where each element has an
00127 // associated weight.
00128 // Assumes weights sum to 1.
00129 mrs_real
00130 statistics::stddevWeighted(const realvec& data, const realvec& weights, mrs_real mean)
00131 {
00132   mrs_real variance = varWeighted(data, weights, mean);
00133   return sqrt(variance);
00134 }
00135 
00136 // Computes the variance for a vector where each element has an
00137 // associated weight.
00138 // Assumes weights sum to 1.
00139 mrs_real
00140 statistics::varWeighted(const realvec& data, const realvec& weights, mrs_real mean)
00141 {
00142   if (data.getSize() != weights.getSize())
00143   {
00144     MRSERR("statistics::varWeighted - wrong size for weights vector!");
00145     return -1.0;
00146   }
00147 
00148   mrs_real sum = 0.0;
00149 
00150   for (mrs_natural i=0; i < data.getSize(); i++)
00151   {
00152     mrs_real w = weights(i);
00153     mrs_real diff = data(i) - mean;
00154 
00155     sum += w * diff * diff;
00156   }
00157 
00158   return sum;
00159 }
00160 
00161 // Computes the weighted skewness (3rd moment) about the given mean value.
00162 // Assumes weights sum to 1
00163 mrs_real
00164 statistics::skewnessWeighted(const realvec& data, const realvec& weights, mrs_real mean)
00165 {
00166   realvec zData = zDataWeighted(data, weights, mean);
00167   return statistics::momentN(zData, weights, 3);
00168 }
00169 
00170 
00171 // Computes the weighted kurtosis (4rd moment) about the given mean value.
00172 // Assumes weights sum to 1
00173 mrs_real
00174 statistics::kurtosisWeighted(const realvec& data, const realvec& weights, mrs_real mean)
00175 {
00176   realvec zData = zDataWeighted(data, weights, mean);
00177   return statistics::momentN(zData, weights, 4) - 3.0;
00178 }
00179