00001 #pragma ident "$Id: Stats.hpp 2254 2010-01-25 20:34:48Z btolman $"
00002
00008 #ifndef INCLUDE_GPSTK_STATS_HPP
00009 #define INCLUDE_GPSTK_STATS_HPP
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "MiscMath.hpp"
00034 #include "Vector.hpp"
00035 #include "Exception.hpp"
00036
00037 namespace gpstk
00038 {
00041
00049 template <class T>
00050 class Stats
00051 {
00052 public:
00054 explicit Stats() { n=0; weighted=false; }
00055
00057 Stats(Vector<T>& X, Vector<T>& W)
00058 {
00059 n = 0;
00060 weighted = false;
00061 Add(X,W);
00062 }
00063
00065 inline void Reset(void) { n=0; weighted=false; W=T(); }
00066
00068 inline unsigned int N(void) const { return n; }
00069
00071 inline T Minimum(void) const { if(n) return min; else return T(); }
00072
00074 inline T Maximum(void) const { if(n) return max; else return T(); }
00075
00077 inline T Average(void) const
00078 {
00079 if(n == 0) return T();
00080 return ave;
00081 }
00082
00084 inline T Variance(void) const
00085 {
00086 if(n <= 1) return T();
00087 return (T(n)*var/T(n-1));
00088 }
00089
00091 inline T StdDev(void) const
00092 {
00093 if(n <= 1) return T();
00094 return SQRT(Variance());
00095 }
00096
00098 inline T Normalization(void) const { return W; }
00099
00101 inline bool Weighted(void) const { return weighted; }
00102
00104 void Add(const T& x, const T& wt_in=T())
00105 {
00106 T wt(ABS(wt_in));
00107 if(wt != T()) { weighted=true; }
00108
00109 if(n == 0) {
00110 min = max = ave = x;
00111 var = T();
00112 W = T();
00113 }
00114 else {
00115 if(x < min) min=x;
00116 if(x > max) max=x;
00117 }
00118
00119 if(weighted) {
00120 if(W+wt > T(1.e-10))
00121 ave += (x-ave)*(wt/(W+wt));
00122 if(n > 0 && W > 1.e-10)
00123 var = (W/(W+wt))*var + (x-ave)*(x-ave)*(wt/W);
00124 W += wt;
00125 }
00126 else {
00127 ave += (x-ave)/T(n+1);
00128 if(n > 0)
00129 var = T(n)*var/T(n+1) + (x-ave)*(x-ave)/T(n);
00130 }
00131
00132 n++;
00133 }
00134
00137 inline void Add(Vector<T>& X, Vector<T> w = Vector<T>())
00138 {
00139 if(w.size() > 0 && w.size() < X.size()) {
00140 Exception e("Inconsistent input: weight vector short");
00141 GPSTK_THROW(e);
00142 }
00143
00144 size_t i;
00145 if(w.size() > 0)
00146 for(i=0; i<X.size(); i++) Add(X(i),w(i));
00147 else
00148 for(i=0; i<X.size(); i++) Add(X(i));
00149 }
00150
00153 void Subtract(const T x, const T wt_in=T())
00154 {
00155 if(n == 0) return;
00156 if(weighted) {
00157 if(W > T(1.e-10)) {
00158 T wt(ABS(wt_in));
00159 if(W-wt > T(1.e-10))
00160 var = (var - (wt/(W-wt))*(x-ave)*(x-ave)) * (W/(W-wt));
00161 else
00162 var = T();
00163 ave = (ave - wt*x/W)*W/(W-wt);
00164 W -= wt;
00165 }
00166 else { ave = var = W = T(); }
00167 }
00168 else {
00169 if(n > 1)
00170 var = (var - (x-ave)*(x-ave)/T(n-1))*T(n)/(T(n)-T(1));
00171 else
00172 var = T();
00173 ave = T(n)*(ave - x/T(n))/(T(n)-T(1));
00174 }
00175 n--;
00176 }
00177
00179 inline void Subtract(Vector<T>& X)
00180 {
00181 for(size_t i=0; i<X.size(); i++) Subtract(X(i));
00182 }
00183
00186 void Load(unsigned int in_n, T in_min, T in_max, T in_ave, T in_var,
00187 bool wtd=false, T norm=1.0)
00188 {
00189 n = in_n;
00190 min = in_min;
00191 max = in_max;
00192 var = in_var;
00193 ave = in_ave;
00194 weighted = wtd;
00195 W = norm;
00196 }
00197
00201 Stats<T>& operator+=(const Stats<T>& S)
00202 {
00203 if(S.n == 0) return *this;
00204 if(n==0) { *this = S; return *this; }
00205 if((weighted && !S.weighted) || (!weighted && S.weighted)) {
00206 Exception e("Stats::operator+= : operands have inconsistent weighting");
00207 GPSTK_THROW(e);
00208 }
00209
00210 if(S.min < min) min=S.min;
00211 if(S.max > max) max=S.max;
00212
00213 T newave, newvar;
00214 if(weighted) {
00215 if(W + S.W > T(1.e-10)) {
00216 newave = W*ave + S.W*S.ave;
00217 newvar = W*var + S.W*S.var + W*ave*ave + S.W*S.ave*S.ave;
00218 W += S.W;
00219 ave = newave/W;
00220
00221 var = newvar/W -ave*ave;
00222 }
00223 }
00224 else {
00225 newave = T(n)*ave + T(S.n)*S.ave;
00226 newvar = T(n)*var + T(S.n)*S.var + T(n)*ave*ave + T(S.n)*S.ave*S.ave;
00227 ave = newave/T(n+S.n);
00228
00229 var = newvar/T(n+S.n) - ave*ave;
00230 }
00231 n += S.n;
00232
00233 return *this;
00234
00235 }
00236
00238
00239 private:
00241 unsigned int n;
00242
00244 T min;
00245
00247 T max;
00248
00250 T ave;
00251
00253 T var;
00254
00256 T W;
00257
00259 bool weighted;
00260
00261 };
00262
00264 template <class T>
00265 std::ostream& operator<<(std::ostream& s, const Stats<T>& ST)
00266 {
00267 std::ofstream savefmt;
00268 savefmt.copyfmt(s);
00269 s << " N = " << ST.N() << (ST.Weighted() ? " ":" not") << " weighted\n";
00270 s << " Minimum = "; s.copyfmt(savefmt); s << ST.Minimum();
00271 s << " Maximum = "; s.copyfmt(savefmt); s << ST.Maximum() << "\n";
00272 s << " Average = "; s.copyfmt(savefmt); s << ST.Average();
00273 s << " Std Dev = "; s.copyfmt(savefmt); s << ST.StdDev();
00274 s << " Variance = "; s.copyfmt(savefmt); s << ST.Variance();
00275 return s;
00276 }
00277
00285 template <class T>
00286 class TwoSampleStats
00287 {
00288 public:
00290 TwoSampleStats() { n=0; }
00291
00293 TwoSampleStats(Vector<T>& X, Vector<T>& Y)
00294 {
00295 n = 0;
00296 Add(X,Y);
00297 }
00298
00300 void Add(const T& X, const T& Y)
00301 {
00302 if(n == 0) {
00303 sumx = sumy = sumx2 = sumy2 = sumxy = T();
00304 xmin = xmax = X;
00305 ymin = ymax = Y;
00306 scalex = scaley = T(1);
00307 }
00308 if(scalex==T(1) && X!=T()) scalex=ABS(X);
00309 if(scaley==T(1) && Y!=T()) scaley=ABS(Y);
00310 sumx += X/scalex;
00311 sumy += Y/scaley;
00312 sumx2 += (X/scalex)*(X/scalex);
00313 sumy2 += (Y/scaley)*(Y/scaley);
00314 sumxy += (X/scalex)*(Y/scaley);
00315 if(X < xmin) xmin=X;
00316 if(X > xmax) xmax=X;
00317 if(Y < ymin) ymin=Y;
00318 if(Y > ymax) ymax=Y;
00319 n++;
00320 }
00321
00323 void Add(const Vector<T>& X, const Vector<T>& Y)
00324 {
00325 size_t m = (X.size() < Y.size() ? X.size() : Y.size());
00326 if(m==0) return;
00327 for(size_t i=0; i<m; i++) Add(X(i),Y(i));
00328 }
00329
00330 void Subtract(const T& X, const T& Y)
00331 {
00332 if(n == 1) {
00333 sumx = sumy = sumx2 = sumy2 = sumxy = T();
00334 xmin = xmax = T();
00335 ymin = ymax = T();
00336 scalex = scaley = T(1);
00337 return;
00338 }
00339
00340 sumx -= X/scalex;
00341 sumy -= Y/scaley;
00342 sumx2 -= (X/scalex)*(X/scalex);
00343 sumy2 -= (Y/scaley)*(Y/scaley);
00344 sumxy -= (X/scalex)*(Y/scaley);
00345 n--;
00346 }
00347
00348 void Subtract(const Vector<T>& X, const Vector<T>& Y)
00349 {
00350 size_t m=(X.size()<Y.size()?X.size():Y.size());
00351 if(m==0) return;
00352 for(size_t i=0; i<m; i++) Subtract(X(i),Y(i));
00353 }
00354
00356 inline void Reset(void) { n=0; }
00357
00359 inline unsigned int N(void) const { return n; }
00361 inline T MinimumX(void) const { if(n) return xmin; else return T(); }
00363 inline T MaximumX(void) const { if(n) return xmax; else return T(); }
00365 inline T MinimumY(void) const { if(n) return ymin; else return T(); }
00367 inline T MaximumY(void) const { if(n) return ymax; else return T(); }
00368
00370 inline T AverageX(void) const
00371 { if(n>0) return (scalex*sumx/T(n)); else return T(); }
00372
00374 inline T AverageY(void) const
00375 { if(n>0) return (scaley*sumy/T(n)); else return T(); }
00376
00378 inline T VarianceX(void) const
00379 {
00380 if(n>1) return scalex*scalex*(sumx2-sumx*sumx/T(n))/T(n-1);
00381 else return T();
00382 }
00383
00385 inline T VarianceY(void) const
00386 {
00387 if(n>1) return scaley*scaley*(sumy2-sumy*sumy/T(n))/T(n-1);
00388 else return T();
00389 }
00390
00392 inline T StdDevX(void) const { return SQRT(VarianceX()); }
00393
00395 inline T StdDevY(void) const { return SQRT(VarianceY()); }
00396
00398 inline T Slope(void) const
00399 {
00400 if(n>0)
00401 return ((scaley/scalex)*(sumxy-sumx*sumy/T(n))/(sumx2-sumx*sumx/T(n)));
00402 else
00403 return T();
00404 }
00405
00407 inline T Intercept(void) const
00408 {
00409 if(n>0)
00410 return (AverageY()-Slope()*AverageX());
00411 else
00412 return T();
00413 }
00414
00416 inline T SigmaSlope(void) const
00417 {
00418 if(n>2)
00419 return (SigmaYX()/(StdDevX()*SQRT(T(n-1))));
00420 else
00421 return T();
00422 }
00423
00425 inline T Correlation(void) const
00426 {
00427 if(n>1)
00428 {
00429 return ( scalex * scaley * (sumxy-sumx*sumy/T(n))
00430 / (StdDevX()*StdDevY()*T(n-1)) );
00431 }
00432 else
00433 return T();
00434 }
00435
00437 inline T SigmaYX(void) const
00438 {
00439 if(n>2)
00440 {
00441 return (StdDevY() * SQRT(T(n-1)/T(n-2))
00442 * SQRT(T(1)-Correlation()*Correlation()) );
00443 }
00444 else return T();
00445 }
00446
00450 TwoSampleStats<T>& operator+=(TwoSampleStats<T>& S)
00451 {
00452 if(n + S.n == 0) return *this;
00453 if(S.xmin < xmin) xmin=S.xmin;
00454 if(S.xmax > xmax) xmax=S.xmax;
00455 if(S.ymin < ymin) ymin=S.ymin;
00456 if(S.ymax > ymax) ymax=S.ymax;
00457 sumx += S.scalex*S.sumx/scalex;
00458 sumy += S.scaley*S.sumy/scaley;
00459 sumx2 += (S.scalex/scalex)*(S.scalex/scalex)*S.sumx2;
00460 sumy2 += (S.scaley/scaley)*(S.scaley/scaley)*S.sumy2;
00461 sumxy += (S.scalex/scalex)*(S.scaley/scaley)*S.sumxy;
00462 n += S.n;
00463 return *this;
00464 }
00465
00466 private:
00468 unsigned int n;
00469 T xmin, xmax, ymin, ymax, scalex, scaley;
00470 T sumx, sumy, sumx2, sumy2, sumxy;
00471
00472 };
00473
00475 template <class T>
00476 std::ostream& operator<<(std::ostream& s, const TwoSampleStats<T>& TSS)
00477 {
00478 std::ofstream savefmt;
00479 savefmt.copyfmt(s);
00480 s << " N = " << TSS.N() << "\n";
00481 s << " Minimum: X = "; s.copyfmt(savefmt); s << TSS.MinimumX();
00482 s << " Y = "; s.copyfmt(savefmt); s << TSS.MinimumY() << "\n";
00483 s << " Maximum: X = "; s.copyfmt(savefmt); s << TSS.MaximumX();
00484 s << " Y = "; s.copyfmt(savefmt); s << TSS.MaximumY() << "\n";
00485 s << " Average: X = "; s.copyfmt(savefmt); s << TSS.AverageX();
00486 s << " Y = "; s.copyfmt(savefmt); s << TSS.AverageY() << "\n";
00487 s << " Std Dev: X = "; s.copyfmt(savefmt); s << TSS.StdDevX();
00488 s << " Y = "; s.copyfmt(savefmt); s << TSS.StdDevY() << "\n";
00489 s << " Variance: X = "; s.copyfmt(savefmt); s << TSS.VarianceX();
00490 s << " Y = "; s.copyfmt(savefmt); s << TSS.VarianceY() << "\n";
00491 s << " Intercept = "; s.copyfmt(savefmt); s << TSS.Intercept();
00492 s << " Slope = "; s.copyfmt(savefmt); s << TSS.Slope();
00493 s << " with uncertainty = "; s.copyfmt(savefmt); s << TSS.SigmaSlope() << "\n";
00494 s << " Conditional uncertainty (sigma y given x) = ";
00495 s.copyfmt(savefmt); s << TSS.SigmaYX();
00496 s << " Correlation = "; s.copyfmt(savefmt); s << TSS.Correlation();
00497 return s;
00498 }
00499
00501 template <class T>
00502 inline T median(const Vector<T>& v)
00503 {
00504 if(v.size()==0) return T();
00505 if(v.size()==1) return v(0);
00506 if(v.size()==2) return (v(0)+v(1))/T(2);
00507
00508 int i,j;
00509 T x;
00510 Vector<T> w(v);
00511 for(i=0; i<v.size(); i++) {
00512 x = w[i] = v(i);
00513 j = i-1;
00514 while(j>=0 && x<w[j]) {
00515 w[j+1] = w[j];
00516 j--;
00517 }
00518 w[j+1] = x;
00519 }
00520 if(v.size() % 2)
00521 x=w[(v.size()+1)/2-1];
00522 else
00523 x=(w[v.size()/2-1]+w[v.size()/2])/T(2);
00524
00525 return x;
00526 }
00527
00529 template <class T>
00530 inline T median(const std::vector<T>& v)
00531 {
00532 if(v.size()==0) return T();
00533 if(v.size()==1) return v[0];
00534 if(v.size()==2) return (v[0]+v[1])/T(2);
00535
00536 int i,j;
00537 T x;
00538 std::vector<T> w(v);
00539 for(i=0; i<v.size(); i++) {
00540 x = w[i] = v[i];
00541 j = i-1;
00542 while(j>=0 && x<w[j]) {
00543 w[j+1] = w[j];
00544 j--;
00545 }
00546 w[j+1] = x;
00547 }
00548 if(v.size() % 2)
00549 x=w[(v.size()+1)/2-1];
00550 else
00551 x=(w[v.size()/2-1]+w[v.size()/2])/T(2);
00552
00553 return x;
00554 }
00555
00557
00558 }
00559
00560 #endif