Theoretica
Scientific Computing
Loading...
Searching...
No Matches
statistics.h
Go to the documentation of this file.
1
5
6#ifndef THEORETICA_STATISTICS_H
7#define THEORETICA_STATISTICS_H
8
9#include "../core/constants.h"
10#include "../core/real_analysis.h"
11#include "../core/special.h"
12#include "../calculus/integral.h"
13#include "../calculus/gauss.h"
14#include "../core/dataset.h"
15
16
17namespace theoretica {
18
19
21 namespace stats {
22
23
29 template<typename Dataset>
30 inline real mean(const Dataset& X) {
31 return arithmetic_mean(X);
32 }
33
34
40 template<typename Dataset>
41 inline real range(const Dataset& X) {
42
43 return max(X) - min(X);
44 }
45
46
53 template<typename Dataset>
54 inline real semidispersion(const Dataset& X) {
55
56 return range(X) / 2.0;
57 }
58
59
67 template<typename Dataset>
69
70 return sqrt(sum_squares(sigma));
71 }
72
73
85 template<typename Dataset1, typename Dataset2>
87
88 if(sigma.size() != mean.size()) {
89 TH_MATH_ERROR("propagate_product", sigma.size(), MathError::InvalidArgument);
90 return nan();
91 }
92
93 // Compute sum of squares of (i_sigma / i_mean)
94 real s = 0;
95 for (unsigned int i = 0; i < sigma.size(); ++i) {
96
97 if(mean[i] == 0) {
98 TH_MATH_ERROR("propagate_product", mean[i], MathError::DivByZero);
99 return nan();
100 }
101
102 s += square(sigma[i] / abs(mean[i]));
103 }
104
105 return sqrt(s);
106 }
107
108
115 template<typename Dataset>
117
118 if(!X.size()) {
119 TH_MATH_ERROR("total_sum_squares", X.size(), MathError::InvalidArgument);
120 return nan();
121 }
122
123 // Running average
124 real avg = X[0];
125
126 // Total sum
127 real s = 0.0;
128
129 for (size_t i = 1; i < X.size(); ++i) {
130
131 const real tmp = avg;
132
133 avg = tmp + (X[i] - tmp) / (i + 1);
134 s += (X[i] - tmp) * (X[i] - avg);
135 }
136
137 return s;
138 }
139
140
150 template<typename Dataset>
151 inline real variance(const Dataset& X, unsigned int constraints = 1) {
152
153 if(X.size() <= constraints) {
154 TH_MATH_ERROR("variance", X.size(), MathError::InvalidArgument);
155 return nan();
156 }
157
158 return total_sum_squares(X) / (X.size() - constraints);
159 }
160
161
171 template<typename Dataset>
172 inline void moments2(
173 const Dataset& X, real& out_mean,
174 real& out_variance, unsigned int constraints = 1) {
175
176 if(X.size() <= constraints) {
177 TH_MATH_ERROR("moments2", X.size(), MathError::InvalidArgument);
178 out_mean = nan();
179 out_variance = nan();
180 return;
181 }
182
183 // Running average
184 real avg = X[0];
185
186 // Total sum
187 real tss = 0.0;
188
189 for (size_t i = 1; i < X.size(); ++i) {
190
191 const real tmp = avg;
192
193 avg = tmp + (X[i] - tmp) / (i + 1);
194 tss += (X[i] - tmp) * (X[i] - avg);
195 }
196
197 out_mean = avg;
198 out_variance = tss / (X.size() - constraints);
199 }
200
201
211 template<typename Dataset>
212 inline real stdev(const Dataset& data, unsigned int constraints = 1) {
213 return sqrt(variance(data, constraints));
214 }
215
216
223 template<typename Dataset>
224 inline real stdom(const Dataset& X) {
225 return sqrt(variance(X) / X.size());
226 }
227
228
238 template<typename Dataset>
240
241 real x_mean = mean(X);
242
243 if(abs(x_mean) < MACH_EPSILON) {
244 TH_MATH_ERROR("standard_relative_error", x_mean, MathError::DivByZero);
245 return nan();
246 }
247
248 return stdev(X) / abs(x_mean);
249 }
250
251
261 template<typename Dataset1, typename Dataset2>
263 const Dataset1& X, const Dataset2& Y, unsigned int constraints = 1) {
264
265 if(X.size() != Y.size() || X.size() <= constraints) {
266 TH_MATH_ERROR("covariance", X.size(), MathError::InvalidArgument);
267 return nan();
268 }
269
270 real s = 0;
271 real X_mean = mean(X);
272 real Y_mean = mean(Y);
273
274 for (unsigned int i = 0; i < X.size(); ++i)
275 s += (X[i] - X_mean) * (Y[i] - Y_mean);
276
277 return s / (X.size() - constraints);
278 }
279
280
289 template<typename Dataset1, typename Dataset2>
291 const Dataset1& X, const Dataset2& Y) {
292
293 return covariance(X, Y) / (stdev(X) * stdev(Y));
294 }
295
296
304 template<typename Dataset>
305 inline real autocorrelation(const Dataset& X, unsigned int n = 1) {
306
307 if(X.size() <= n) {
308 TH_MATH_ERROR("autocorrelation", X.size(), MathError::InvalidArgument);
309 return nan();
310 }
311
312 const real mu = mean(X);
313 real num = 0;
314 real den = 0;
315
316 for (unsigned int i = 0; i < X.size(); ++i)
317 den += square(X[i] - mu);
318
319 for (unsigned int i = n; i < X.size(); ++i) {
320
321 const real delta = X[i] - mu;
322 num += delta * (X[i - n] - mu);
323 }
324
325 return num / den;
326 }
327
328
335 template<typename Dataset>
337
338 real mu = mean(X);
339 real res = 0;
340
341 for (real x : X)
342 res += abs(x - mu);
343
344 return res / X.size();
345 }
346
347
354 template<typename Dataset>
355 inline real skewness(const Dataset& X) {
356
357 real mu, sigma;
358 real res = 0;
359
360 moments2(X, mu, sigma);
361 sigma = sqrt(sigma);
362
363 for (real x : X)
364 res += cube((x - mu) / sigma);
365
366 return res / X.size();
367 }
368
369
376 template<typename Dataset>
377 inline real kurtosis(const Dataset& X) {
378
379 real mu, sigma;
380 real res = 0;
381
382 moments2(X, mu, sigma);
383 sigma = sqrt(sigma);
384
385 for (real x : X)
386 res += pow((x - mu) / sigma, 4);
387
388 return (res / X.size()) - 3;
389 }
390
391
402 template<typename RealFunction>
404
405 return integral_hermite(
406 [=](real x) {
407 return g(SQRT2 * sigma * x + mean);
408 }
409 ) / SQRTPI;
410 }
411
412
422
423 return (x - mean) / sigma;
424 }
425
426
432 template<typename Dataset>
434
435 real mu, sigma;
436 moments2(X, mu, sigma);
437 sigma = sqrt(sigma);
438
439 return map([mu, sigma](real x) { return z_score(x, mu, sigma); }, X);
440 }
441
442
454 template<typename Dataset1, typename Dataset2, typename Dataset3>
456 const Dataset1& O, const Dataset2& E, const Dataset3& sigma) {
457
458 if(O.size() != E.size() || E.size() != sigma.size()) {
459 TH_MATH_ERROR("chi_square", E.size(), MathError::InvalidArgument);
460 return nan();
461 }
462
463 real c_sqr = 0;
464
465 for (unsigned int i = 0; i < O.size(); ++i) {
466
467 if(abs(sigma[i]) < MACH_EPSILON) {
468 TH_MATH_ERROR("chi_square", sigma[i], MathError::DivByZero);
469 return nan();
470 }
471
472 c_sqr += square((O[i] - E[i]) / sigma[i]);
473 }
474
475 return c_sqr;
476 }
477
478
491 inline real pvalue_chi2(real chi_sqr, unsigned int ndf) {
492
493 if(ndf == 0) {
494 TH_MATH_ERROR("pvalue_chi2", ndf, MathError::InvalidArgument);
495 return nan();
496 }
497
499 return 1.0;
500
501 // For ndf >= 260 use the Gaussian approximation
502 // as the coefficients are not stable
503 if(ndf >= 260) {
504
505 const real new_x = (chi_sqr - ndf) / sqrt(2.0 * ndf);
506
507 // For really low Chi-squared the Gaussian is
508 // below tolerance value for integration
509 if(new_x < 0) {
510
511 if(new_x < -3)
512 return 1 - integral_inf_riemann([=](real x) {
513 return exp(-x * x / 2) / SQRTPI / SQRT2;
514 }, -new_x, 1E-16, 25);
515
516 return 0.5 + integral_romberg([=](real x) {
517 return exp(-x * x / 2) / SQRTPI / SQRT2;
518 }, new_x, 0, 1E-16);
519 } else {
520
521 if(new_x > 3)
522 return integral_inf_riemann([=](real x) {
523 return exp(-x * x / 2) / SQRTPI / SQRT2;
524 }, new_x, 1E-16, 25);
525
526 return 0.5 - integral_romberg([=](real x) {
527 return exp(-x * x / 2) / SQRTPI / SQRT2;
528 }, 0, new_x, 1E-16);
529 }
530 }
531
532 // Compute the coefficient using a stable equivalent formula
533 const real coeff = exp(-special::lngamma(ndf / 2.0) - chi_sqr / 2.0);
534
535 // Use different methods when Gauss-Laguerre is not numerically stable
536 if((ndf > 70 && chi_sqr < (ndf / 2.0))) {
537
538 // Use equivalent formula around potential singularity
539 real res = integral_romberg([=](real x) {
540 return pow(sqrt(x + chi_sqr / 2), ndf - 2) * exp(-x);
541 }, 0, 1, 1E-12);
542
543 res += integral_inf_riemann([=](real x) {
544 return exp((ndf - 2) / 2.0 * ln(x + chi_sqr / 2) - x);
545 }, 1, ndf / 2, 1E-12, 25);
546
547 return coeff * res;
548 }
549
550 // Approximate the integral using Gauss-Laguerre quadrature
551 return coeff * integral_gauss(
552 [=](real x) {
553 return pow(sqrt(x + chi_sqr / 2), ndf - 2);
554 }, tables::laguerre_roots_16, tables::laguerre_weights_16, 16);
555 }
556
557
571 template<typename Dataset1, typename Dataset2, typename Dataset3>
573 const Dataset1& X, const Dataset2& Y,
574 const Dataset3& sigma, real intercept, real slope, bool reduced = false) {
575
576 if(X.size() != Y.size() || X.size() != sigma.size()) {
578 "chi_square_linear",
580 return nan();
581 }
582
583 real chi_squared = 0;
584 for (unsigned int i = 0; i < X.size(); ++i) {
585
586 if(abs(sigma[i]) <= MACH_EPSILON) {
587 TH_MATH_ERROR("chi_square_linear", sigma[i], MathError::DivByZero);
588 return nan();
589 }
590
591 chi_squared += square((Y[i] - intercept - slope * X[i]) / sigma[i]);
592 }
593
594 if(reduced)
595 chi_squared /= (X.size() - 2);
596
597 return chi_squared;
598 }
599 }
600}
601
602#endif
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:219
real lngamma(real x)
Log Gamma special function of real argument.
Definition special.h:59
void moments2(const Dataset &X, real &out_mean, real &out_variance, unsigned int constraints=1)
Compute the mean and the variance of a dataset in a single pass, using Welford's method,...
Definition statistics.h:172
real semidispersion(const Dataset &X)
Computes the maximum semidispersion of a data set defined as .
Definition statistics.h:54
real stdev(const histogram &h)
Compute the standard deviation of the values of a histogram.
Definition histogram.h:366
Dataset normalize_z_score(const Dataset &X)
Normalize a data set using Z-score normalization.
Definition statistics.h:433
real autocorrelation(const Dataset &X, unsigned int n=1)
Compute the lag-n autocorrelation of a dataset as .
Definition statistics.h:305
real pvalue_chi2(real chi_sqr, unsigned int ndf)
Compute the (right-tailed) p-value associated to a computed Chi-square value as the integral of the C...
Definition statistics.h:491
real chi_square_linear(const Dataset1 &X, const Dataset2 &Y, const Dataset3 &sigma, real intercept, real slope, bool reduced=false)
Compute the chi-square on a linear regression, as the sum of the squares of the residuals divided by ...
Definition statistics.h:572
real covariance(const Dataset1 &X, const Dataset2 &Y, unsigned int constraints=1)
Compute the covariance between two datasets with the given number of constraints.
Definition statistics.h:262
real propagate_product(const Dataset1 &sigma, const Dataset2 &mean)
Propagate the error over a product of random variables under quadrature, as , where each corresponds...
Definition statistics.h:86
real standard_relative_error(const Dataset &X)
Compute the relative error on a dataset using estimates of its mean and standard deviation,...
Definition statistics.h:239
real total_sum_squares(const Dataset &X)
Compute the total sum of squares (TSS) of a given dataset as using Welford's one-pass method.
Definition statistics.h:116
real variance(const histogram &h)
Compute the variance of the values of a histogram.
Definition histogram.h:354
real absolute_deviation(const Dataset &X)
Compute the mean absolute deviation of a dataset as .
Definition statistics.h:336
real gaussian_expectation(RealFunction g, real mean, real sigma)
Compute the expectation value of a given function with respect to a Gaussian distribution with the gi...
Definition statistics.h:403
real stdom(const Dataset &X)
Compute the standard deviation of the mean given a dataset.
Definition statistics.h:224
real propagate_sum(const Dataset &sigma)
Propagate the error over a sum of random variables under quadrature, as , where each corresponds to ...
Definition statistics.h:68
real range(const Dataset &X)
Computes the range of a data set, defined as .
Definition statistics.h:41
real mean(const histogram &h)
Compute the mean of the values of a histogram.
Definition histogram.h:342
real skewness(const Dataset &X)
Compute the skewness of a dataset as .
Definition statistics.h:355
real kurtosis(const Dataset &X)
Compute the normalized kurtosis of a dataset as .
Definition statistics.h:377
real chi_square(const Dataset1 &O, const Dataset2 &E, const Dataset3 &sigma)
Compute the chi-square from the set of observed quantities, expected quantities and errors.
Definition statistics.h:455
real tss(const histogram &h)
Compute the total sum of squares of the values of the histogram.
Definition histogram.h:348
real correlation_coefficient(const Dataset1 &X, const Dataset2 &Y)
Compute Pearson's correlation coefficient R between two datasets.
Definition statistics.h:290
real z_score(real x, real mean, real sigma)
Compute the Z-score of an observed value with respect to a Gaussian distribution with the given param...
Definition statistics.h:421
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
double real
A real number, defined as a floating point type.
Definition constants.h:207
real arithmetic_mean(const Dataset &data)
Compute the arithmetic mean of a set of values.
Definition dataset.h:371
auto min(const Vector &X)
Finds the minimum value inside a dataset.
Definition dataset.h:347
dual2 sqrt(dual2 x)
Compute the square root of a second order dual number.
Definition dual2_functions.h:54
Vector2 & map(Function f, const Vector1 &src, Vector2 &dest)
Overwrite a vector by applying a function to the elements of another vector.
Definition dataset.h:263
dual2 ln(dual2 x)
Compute the natural logarithm of a second order dual number.
Definition dual2_functions.h:195
dual2 abs(dual2 x)
Compute the absolute value of a second order dual number.
Definition dual2_functions.h:242
constexpr real SQRTPI
The square root of Pi.
Definition constants.h:243
dual2 exp(dual2 x)
Compute the exponential of a second order dual number.
Definition dual2_functions.h:138
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
real integral_inf_riemann(real_function f, real a, real step_sz=1, real tol=CALCULUS_INTEGRAL_TOL, unsigned int max_iter=100)
Integrate a function from a point up to infinity by integrating it by steps, stopping execution when ...
Definition integral.h:489
auto max(const Vector &X)
Finds the maximum value inside a dataset.
Definition dataset.h:326
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:74
real integral_gauss(RealFunction f, const std::vector< real > &x, const std::vector< real > &w)
Use Gaussian quadrature using the given points and weights.
Definition integral.h:220
@ InvalidArgument
Invalid argument.
@ DivByZero
Division by zero.
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216
constexpr real E
The Euler mathematical constant (e)
Definition constants.h:246
real integral_hermite(RealFunction f, const std::vector< real > &x)
Use Gauss-Hermite quadrature of arbitrary degree to approximate an integral over (-inf,...
Definition integral.h:451
real integral_romberg(RealFunction f, real a, real b, real tolerance=CALCULUS_INTEGRAL_TOL, size_t max_iter=16)
Approximate the definite integral of an arbitrary function using Romberg's method to the given tolera...
Definition integral.h:174
constexpr real SQRT2
The square root of 2.
Definition constants.h:270
dual2 square(dual2 x)
Return the square of a second order dual number.
Definition dual2_functions.h:23
auto sum_squares(const Vector &X)
Sum the squares of a set of values.
Definition dataset.h:123
dual2 pow(dual2 x, int n)
Compute the n-th power of a second order dual number.
Definition dual2_functions.h:41
dual2 cube(dual2 x)
Return the cube of a second order dual number.
Definition dual2_functions.h:29