A toolkit for working with phylogenetic data.
v0.24.0
statistics.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_MATH_STATISTICS_H_
2 #define GENESIS_UTILS_MATH_STATISTICS_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2020 Lucas Czech and HITS gGmbH
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
37 
38 #include <algorithm>
39 #include <cassert>
40 #include <cmath>
41 #include <cstddef>
42 #include <functional>
43 #include <limits>
44 #include <stdexcept>
45 #include <utility>
46 #include <vector>
47 
48 namespace genesis {
49 namespace utils {
50 
51 // =================================================================================================
52 // Static Assersions
53 // =================================================================================================
54 
55 // We need to make sure that doubles and their infinities behave the way we expect!
56 
57 static_assert(
58  std::numeric_limits<double>::is_iec559,
59  "IEC 559/IEEE 754 floating-point types required (wrong double type)."
60 );
61 static_assert(
62  std::numeric_limits<double>::has_infinity,
63  "IEC 559/IEEE 754 floating-point types required (does not have infinity)."
64 );
65 static_assert(
66  std::numeric_limits<double>::has_quiet_NaN,
67  "IEC 559/IEEE 754 floating-point types required (does not have quite NaN)."
68 );
69 static_assert(
70  - std::numeric_limits<double>::infinity() < std::numeric_limits<double>::lowest(),
71  "IEC 559/IEEE 754 floating-point types required (infinity is not the lowest value)."
72 );
73 
74 // Clang fails to compile the following assertions, because of missing const expr markers
75 // in their std lib implementation. We hence need to skip those tests for clang :-(
76 // Hopefully, the above assertions are enough to cover the basics.
77 
78 #ifndef __clang__
79 
80 static_assert(
81  std::isinf( - std::numeric_limits<double>::infinity() ),
82  "IEC 559/IEEE 754 floating-point types required (infinity is not working properly)."
83 );
84 static_assert(
85  std::isinf( -1 * std::numeric_limits<double>::infinity()),
86  "IEC 559/IEEE 754 floating-point types required."
87 );
88 static_assert(
89  -1 * std::numeric_limits<double>::infinity() < std::numeric_limits<double>::lowest(),
90  "IEC 559/IEEE 754 floating-point types required."
91 );
92 
93 #endif // __clang__
94 
95 // =================================================================================================
96 // Structures and Classes
97 // =================================================================================================
98 
104 template< typename T >
106 {
107  T min;
108  T max;
109 };
110 
118 {
119  double mean;
120  double stddev;
121 };
122 
127 struct Quartiles
128 {
129  double q0 = 0.0;
130  double q1 = 0.0;
131  double q2 = 0.0;
132  double q3 = 0.0;
133  double q4 = 0.0;
134 };
135 
136 // =================================================================================================
137 // Standard Helper Functions
138 // =================================================================================================
139 
149 template <class ForwardIterator>
150 std::pair<size_t, size_t> count_finite_elements( ForwardIterator first, ForwardIterator last )
151 {
152  // Prepare result.
153  size_t valid = 0;
154  size_t total = 0;
155 
156  // Iterate.
157  while( first != last ) {
158  if( std::isfinite( *first ) ) {
159  ++valid;
160  }
161  ++total;
162  ++first;
163  }
164 
165  return { valid, total };
166 }
167 
174 template <class ForwardIterator>
175 double finite_minimum( ForwardIterator first, ForwardIterator last )
176 {
177  // Prepare result.
178  double min = std::numeric_limits<double>::max();
179  size_t cnt = 0;
180 
181  // Iterate.
182  while( first != last ) {
183  if( std::isfinite( *first ) ) {
184  if( *first < min ) {
185  min = *first;
186  }
187  ++cnt;
188  }
189  ++first;
190  }
191 
192  // If there are no valid elements, return nan.
193  if( cnt == 0 ) {
194  return std::numeric_limits<double>::quiet_NaN();
195  }
196 
197  return min;
198 }
199 
206 template <class ForwardIterator>
207 double finite_maximum( ForwardIterator first, ForwardIterator last )
208 {
209  // Prepare result.
210  double max = std::numeric_limits<double>::lowest();
211  size_t cnt = 0;
212 
213  // Iterate.
214  while( first != last ) {
215  if( std::isfinite( *first ) ) {
216  if( *first > max ) {
217  max = *first;
218  }
219  ++cnt;
220  }
221  ++first;
222  }
223 
224  // If there are no valid elements, return nan.
225  if( cnt == 0 ) {
226  return std::numeric_limits<double>::quiet_NaN();
227  }
228 
229  return max;
230 }
231 
238 template <class ForwardIterator>
239 MinMaxPair<double> finite_minimum_maximum( ForwardIterator first, ForwardIterator last )
240 {
241  // Prepare result.
242  MinMaxPair<double> result;
243  result.min = std::numeric_limits<double>::max();
244  result.max = std::numeric_limits<double>::lowest();
245  size_t cnt = 0;
246 
247  // Iterate.
248  while( first != last ) {
249  if( std::isfinite( *first ) ) {
250  if( *first < result.min ) {
251  result.min = *first;
252  }
253  if( *first > result.max ) {
254  result.max = *first;
255  }
256  ++cnt;
257  }
258  ++first;
259  }
260 
261  // If there are no valid elements, return nan.
262  if( cnt == 0 ) {
263  result.min = std::numeric_limits<double>::quiet_NaN();
264  result.max = std::numeric_limits<double>::quiet_NaN();
265  }
266 
267  return result;
268 }
269 
270 // =================================================================================================
271 // Normalization and Compositional Data Analysis
272 // =================================================================================================
273 
287 template <class ForwardIterator>
288 void closure( ForwardIterator first, ForwardIterator last )
289 {
290  // Prepare result.
291  double sum = 0.0;
292  size_t cnt = 0;
293 
294  // Sum up elements.
295  auto it = first;
296  while( it != last ) {
297  if( std::isfinite( *it ) ) {
298  if( *it < 0.0 ) {
299  throw std::invalid_argument(
300  "Cannot calculate closure of negative numbers."
301  );
302  }
303 
304  sum += *it;
305  ++cnt;
306  }
307  ++it;
308  }
309 
310  // If there are no valid elements, return.
311  if( cnt == 0 ) {
312  return;
313  }
314 
315  // Make the closure.
316  it = first;
317  while( it != last ) {
318  if( std::isfinite( *it ) ) {
319  *it /= sum;
320  }
321  ++it;
322  }
323 }
324 
330 inline void closure( std::vector<double>& vec )
331 {
332  return closure( vec.begin(), vec.end() );
333 }
334 
335 // =================================================================================================
336 // Mean Stddev
337 // =================================================================================================
338 
357 template <class ForwardIterator>
358 MeanStddevPair mean_stddev( ForwardIterator first, ForwardIterator last, double epsilon = -1.0 )
359 {
360  // Prepare result.
361  MeanStddevPair result;
362  result.mean = 0.0;
363  result.stddev = 0.0;
364  size_t count = 0;
365 
366  // Sum up elements.
367  auto it = first;
368  while( it != last ) {
369  if( std::isfinite( *it ) ) {
370  result.mean += *it;
371  ++count;
372  }
373  ++it;
374  }
375 
376  // If there are no valid elements, return an all-zero result.
377  if( count == 0 ) {
378  return result;
379  }
380 
381  // Calculate mean.
382  result.mean /= static_cast<double>( count );
383 
384  // Calculate std dev.
385  it = first;
386  while( it != last ) {
387  if( std::isfinite( *it ) ) {
388  result.stddev += (( *it - result.mean ) * ( *it - result.mean ));
389  }
390  ++it;
391  }
392  assert( count > 0 );
393  result.stddev /= static_cast<double>( count );
394  result.stddev = std::sqrt( result.stddev );
395 
396  // The following in an inelegant (but usual) way to handle near-zero values,
397  // which later would cause a division by zero.
398  assert( result.stddev >= 0.0 );
399  if( result.stddev <= epsilon ){
400  result.stddev = 1.0;
401  }
402 
403  return result;
404 }
405 
413 inline MeanStddevPair mean_stddev( std::vector<double> const& vec, double epsilon = -1.0 )
414 {
415  return mean_stddev( vec.begin(), vec.end(), epsilon );
416 }
417 
418 // =================================================================================================
419 // Arithmetic Mean
420 // =================================================================================================
421 
436 template <class ForwardIterator>
437 double arithmetic_mean( ForwardIterator first, ForwardIterator last )
438 {
439  // Prepare result.
440  double mean = 0.0;
441  size_t count = 0;
442 
443  // Sum up elements.
444  auto it = first;
445  while( it != last ) {
446  if( std::isfinite( *it ) ) {
447  mean += *it;
448  ++count;
449  }
450  ++it;
451  }
452 
453  // If there are no valid elements, return an all-zero result.
454  if( count == 0 ) {
455  assert( mean == 0.0 );
456  return mean;
457  }
458 
459  // Calculate mean.
460  assert( count > 0 );
461  return mean / static_cast<double>( count );
462 }
463 
471 inline double arithmetic_mean( std::vector<double> const& vec )
472 {
473  return arithmetic_mean( vec.begin(), vec.end() );
474 }
475 
491 template <class ForwardIterator>
493  ForwardIterator first_value, ForwardIterator last_value,
494  ForwardIterator first_weight, ForwardIterator last_weight
495 ) {
496  double num = 0.0;
497  double den = 0.0;
498  size_t cnt = 0;
499 
500  // Multiply elements.
501  for_each_finite_pair( first_value, last_value, first_weight, last_weight, [&]( double value, double weight ){
502  if( weight < 0.0 ) {
503  throw std::invalid_argument(
504  "Cannot calculate weighted arithmetic mean with negative weights."
505  );
506  }
507 
508  num += weight * value;
509  den += weight;
510  ++cnt;
511  });
512 
513  // If there are no valid elements, return an all-zero result.
514  if( cnt == 0 ) {
515  return 0.0;
516  }
517  if( den == 0.0 ) {
518  throw std::invalid_argument(
519  "Cannot calculate weighted arithmetic mean with all weights being 0."
520  );
521  }
522 
523  // Return the result.
524  assert( cnt > 0 );
525  assert( den > 0.0 );
526  return ( num / den );
527 }
528 
538  std::vector<double> const& values,
539  std::vector<double> const& weights
540 ) {
541  return weighted_arithmetic_mean( values.begin(), values.end(), weights.begin(), weights.end() );
542 }
543 
544 // =================================================================================================
545 // Geometric Mean
546 // =================================================================================================
547 
562 template <class ForwardIterator>
563 double geometric_mean( ForwardIterator first, ForwardIterator last )
564 {
565  double sum = 0.0;
566  size_t count = 0;
567 
568  // Iterate elements. For numeric stability, we use sum of logs instead of products;
569  // otherwise, we run into overflows too quickly!
570  auto it = first;
571  while( it != last ) {
572  if( std::isfinite( *it ) ) {
573  if( *it <= 0.0 ) {
574  throw std::invalid_argument(
575  "Cannot calculate geometric mean of non-positive numbers."
576  );
577  }
578  sum += std::log( *it );
579  ++count;
580  }
581  ++it;
582  }
583 
584  // If there are no valid elements, return an all-zero result.
585  if( count == 0 ) {
586  return 0.0;
587  }
588 
589  // Return the result.
590  assert( count > 0 );
591  assert( std::isfinite( sum ));
592  return std::exp( sum / static_cast<double>( count ));
593 }
594 
601 inline double geometric_mean( std::vector<double> const& vec )
602 {
603  return geometric_mean( vec.begin(), vec.end() );
604 }
605 
634 template <class ForwardIterator>
636  ForwardIterator first_value, ForwardIterator last_value,
637  ForwardIterator first_weight, ForwardIterator last_weight
638 ) {
639  double num = 0.0;
640  double den = 0.0;
641  size_t cnt = 0;
642 
643  // Multiply elements.
644  for_each_finite_pair( first_value, last_value, first_weight, last_weight, [&]( double value, double weight ){
645  if( value <= 0.0 ) {
646  throw std::invalid_argument(
647  "Cannot calculate weighted geometric mean of non-positive values."
648  );
649  }
650  if( weight < 0.0 ) {
651  throw std::invalid_argument(
652  "Cannot calculate weighted geometric mean with negative weights."
653  );
654  }
655 
656  num += weight * std::log( value );
657  den += weight;
658  ++cnt;
659  });
660 
661  // If there are no valid elements, return an all-zero result.
662  if( cnt == 0 ) {
663  return 0.0;
664  }
665  if( den == 0.0 ) {
666  throw std::invalid_argument(
667  "Cannot calculate weighted geometric mean with all weights being 0."
668  );
669  }
670 
671  // Return the result.
672  assert( cnt > 0 );
673  assert( std::isfinite( num ));
674  assert( std::isfinite( den ) && ( den > 0.0 ));
675  return std::exp( num / den );
676 }
677 
687  std::vector<double> const& values,
688  std::vector<double> const& weights
689 ) {
690  return weighted_geometric_mean( values.begin(), values.end(), weights.begin(), weights.end() );
691 }
692 
693 // =================================================================================================
694 // Median
695 // =================================================================================================
696 
706 template <class RandomAccessIterator>
707 double median( RandomAccessIterator first, RandomAccessIterator last )
708 {
709  // Checks.
710  if( ! std::is_sorted( first, last )) {
711  throw std::runtime_error( "Range has to be sorted for median calculation." );
712  }
713  auto const size = static_cast<size_t>( std::distance( first, last ));
714  if( size == 0 ) {
715  return 0.0;
716  }
717 
718  // Even or odd size? Median is calculated differently.
719  if( size % 2 == 0 ) {
720 
721  // Get the two middle positions.
722  size_t pl = size / 2 - 1;
723  size_t pu = size / 2;
724  assert( pl < size && pu < size );
725 
726  return ( *(first + pl) + *(first + pu) ) / 2.0;
727 
728  } else {
729 
730  // Int division, rounds down. This is what we want.
731  size_t p = size / 2;
732  assert( p < size );
733 
734  return *(first + p);
735  }
736 }
737 
743 inline double median( std::vector<double> const& vec )
744 {
745  return median( vec.begin(), vec.end() );
746 }
747 
748 // =================================================================================================
749 // Quartiles
750 // =================================================================================================
751 
758 template <class RandomAccessIterator>
759 Quartiles quartiles( RandomAccessIterator first, RandomAccessIterator last )
760 {
761  // Prepare result.
762  Quartiles result;
763 
764  // Checks.
765  if( ! std::is_sorted( first, last )) {
766  throw std::runtime_error( "Range has to be sorted for quartiles calculation." );
767  }
768  auto const size = static_cast<size_t>( std::distance( first, last ));
769  if( size == 0 ) {
770  return result;
771  }
772 
773  // Set min, 50% and max.
774  result.q0 = *first;
775  result.q2 = median( first, last );
776  result.q4 = *(first + size - 1);
777 
778  // Even or odd size? Quartiles are calculated differently.
779  // This could be done shorter, but this way is more expressive.
780  if( size % 2 == 0 ) {
781 
782  // Even: Split exaclty in halves.
783  result.q1 = median( first, first + size / 2 );
784  result.q3 = median( first + size / 2, first + size );
785 
786  } else {
787 
788  // Odd: Do not include the median value itself.
789  result.q1 = median( first, first + size / 2 );
790  result.q3 = median( first + size / 2 + 1, first + size );
791  }
792 
793  return result;
794 }
795 
801 inline Quartiles quartiles( std::vector<double> const& vec )
802 {
803  return quartiles( vec.begin(), vec.end() );
804 }
805 
806 // =================================================================================================
807 // Dispersion
808 // =================================================================================================
809 
818 inline double coefficient_of_variation( MeanStddevPair const& ms )
819 {
820  return ms.stddev / ms.mean;
821 }
822 
826 inline std::vector<double> coefficient_of_variation( std::vector<MeanStddevPair> const& ms )
827 {
828  auto res = std::vector<double>( ms.size() );
829  for( size_t i = 0; i < ms.size(); ++i ) {
830  res[ i ] = coefficient_of_variation( ms[i] );
831  }
832  return res;
833 }
834 
844 inline double index_of_dispersion( MeanStddevPair const& ms )
845 {
846  return ms.stddev * ms.stddev / ms.mean;
847 }
848 
852 inline std::vector<double> index_of_dispersion( std::vector<MeanStddevPair> const& ms )
853 {
854  auto res = std::vector<double>( ms.size() );
855  for( size_t i = 0; i < ms.size(); ++i ) {
856  res[ i ] = index_of_dispersion( ms[i] );
857  }
858  return res;
859 }
860 
869 {
870  return ( q.q3 - q.q1 ) / ( q.q3 + q.q1 );
871 }
872 
876 inline std::vector<double> quartile_coefficient_of_dispersion( std::vector<Quartiles> const& q )
877 {
878  auto res = std::vector<double>( q.size() );
879  for( size_t i = 0; i < q.size(); ++i ) {
880  res[ i ] = quartile_coefficient_of_dispersion( q[i] );
881  }
882  return res;
883 }
884 
885 // =================================================================================================
886 // Correlation Coefficients
887 // =================================================================================================
888 
901 template <class ForwardIteratorA, class ForwardIteratorB>
903  ForwardIteratorA first_a, ForwardIteratorA last_a,
904  ForwardIteratorB first_b, ForwardIteratorB last_b
905 ) {
906  // Calculate means.
907  double mean_a = 0.0;
908  double mean_b = 0.0;
909  size_t count = 0;
910  for_each_finite_pair( first_a, last_a, first_b, last_b, [&]( double val_a, double val_b ){
911  mean_a += val_a;
912  mean_b += val_b;
913  ++count;
914  });
915  if( count == 0 ) {
916  return std::numeric_limits<double>::quiet_NaN();
917  }
918  assert( count > 0 );
919  mean_a /= static_cast<double>( count );
920  mean_b /= static_cast<double>( count );
921 
922  // Calculate PCC parts.
923  double numerator = 0.0;
924  double std_dev_a = 0.0;
925  double std_dev_b = 0.0;
926  for_each_finite_pair( first_a, last_a, first_b, last_b, [&]( double val_a, double val_b ){
927  double const d1 = val_a - mean_a;
928  double const d2 = val_b - mean_b;
929  numerator += d1 * d2;
930  std_dev_a += d1 * d1;
931  std_dev_b += d2 * d2;
932  });
933 
934  // Calculate PCC, and assert that it is in the correct range
935  // (or not a number, which can happen if the std dev is 0.0, e.g. in all-zero vectors).
936  auto const pcc = numerator / ( std::sqrt( std_dev_a ) * std::sqrt( std_dev_b ) );
937  assert(( -1.0 <= pcc && pcc <= 1.0 ) || ( ! std::isfinite( pcc ) ));
938  return pcc;
939 }
940 
947  std::vector<double> const& vec_a,
948  std::vector<double> const& vec_b
949 ) {
951  vec_a.begin(), vec_a.end(), vec_b.begin(), vec_b.end()
952  );
953 }
954 
963 template <class RandomAccessIteratorA, class RandomAccessIteratorB>
965  RandomAccessIteratorA first_a, RandomAccessIteratorA last_a,
966  RandomAccessIteratorB first_b, RandomAccessIteratorB last_b
967 ) {
968  // Get cleaned results. We need to make these copies, as we need to calculate the fractional
969  // ranking on them, which would change if we used our normal for_each_finite_pair here...
970  auto const cleaned = finite_pairs( first_a, last_a, first_b, last_b );
971 
972  // Get the ranking of both vectors.
973  auto ranks_a = ranking_fractional( cleaned.first );
974  auto ranks_b = ranking_fractional( cleaned.second );
975  assert( ranks_a.size() == ranks_b.size() );
976 
977  return pearson_correlation_coefficient( ranks_a, ranks_b );
978 }
979 
986  std::vector<double> const& vec_a,
987  std::vector<double> const& vec_b
988 ) {
990  vec_a.begin(), vec_a.end(), vec_b.begin(), vec_b.end()
991  );
992 }
993 
1002 inline double fisher_transformation( double correlation_coefficient )
1003 {
1004  auto const r = correlation_coefficient;
1005  if( r < -1.0 || r > 1.0 ) {
1006  throw std::invalid_argument(
1007  "Cannot apply fisher transformation to value " + std::to_string( r ) +
1008  " outside of [ -1.0, 1.0 ]."
1009  );
1010  }
1011 
1012  // LOG_DBG << "formula " << 0.5 * log( ( 1.0 + r ) / ( 1.0 - r ) );
1013  // LOG_DBG << "simple " << std::atanh( r );
1014  return std::atanh( r );
1015 }
1016 
1022 inline std::vector<double> fisher_transformation( std::vector<double> const& correlation_coefficients )
1023 {
1024  auto res = correlation_coefficients;
1025  for( auto& elem : res ) {
1026  elem = fisher_transformation( elem );
1027  }
1028  return res;
1029 }
1030 
1031 } // namespace utils
1032 } // namespace genesis
1033 
1034 #endif // include guard
double geometric_mean(ForwardIterator first, ForwardIterator last)
Calculate the geometric mean of a range of positive numbers.
Definition: statistics.hpp:563
double finite_minimum(ForwardIterator first, ForwardIterator last)
Return the minimum of a range of double values.
Definition: statistics.hpp:175
Provides some valuable algorithms that are not part of the C++ 11 STL.
Store a pair of min and max values.
Definition: statistics.hpp:105
double pearson_correlation_coefficient(ForwardIteratorA first_a, ForwardIteratorA last_a, ForwardIteratorB first_b, ForwardIteratorB last_b)
Calculate the Pearson Correlation Coefficient between two ranges of double.
Definition: statistics.hpp:902
double fisher_transformation(double correlation_coefficient)
Apply Fisher z-transformation to a correlation coefficient.
std::pair< std::vector< double >, std::vector< double > > finite_pairs(ForwardIteratorA first_a, ForwardIteratorA last_a, ForwardIteratorB first_b, ForwardIteratorB last_b)
Helper function that cleans two ranges of double of the same length from non-finite values...
Definition: common.hpp:189
double median(const Histogram &h)
double sum(const Histogram &h)
Quartiles quartiles(RandomAccessIterator first, RandomAccessIterator last)
Calculate the Quartiles of a sorted range of double values.
Definition: statistics.hpp:759
double quartile_coefficient_of_dispersion(Quartiles const &q)
Calculate the quartile_coefficient_of_dispersion.
Definition: statistics.hpp:868
Container namespace for all symbols of genesis in order to keep them separate when used as a library...
double weighted_arithmetic_mean(ForwardIterator first_value, ForwardIterator last_value, ForwardIterator first_weight, ForwardIterator last_weight)
Calculate the weighted arithmetic mean of a range of double values.
Definition: statistics.hpp:492
void closure(ForwardIterator first, ForwardIterator last)
Calculate the closure of a range of numbers.
Definition: statistics.hpp:288
std::vector< double > ranking_fractional(RandomAccessIterator first, RandomAccessIterator last)
Return the ranking of the values in the given range, using Fractional ranking ("1 2...
Definition: ranking.hpp:260
double weighted_geometric_mean(ForwardIterator first_value, ForwardIterator last_value, ForwardIterator first_weight, ForwardIterator last_weight)
Calculate the weighted geometric mean of a range of positive numbers.
Definition: statistics.hpp:635
double mean(const Histogram &h)
Compute the bin-weighted arithmetic mean.
double coefficient_of_variation(MeanStddevPair const &ms)
Calculate the index of dispersion.
Definition: statistics.hpp:818
double arithmetic_mean(ForwardIterator first, ForwardIterator last)
Calculate the arithmetic mean of a range of numbers.
Definition: statistics.hpp:437
void for_each_finite_pair(ForwardIteratorA first_a, ForwardIteratorA last_a, ForwardIteratorB first_b, ForwardIteratorB last_b, std::function< void(double value_a, double value_b)> execute)
Iterate two ranges of double values in parallel, and execute a function for each pair of values from ...
Definition: common.hpp:223
Store a mean and a standard deviation value.
Definition: statistics.hpp:117
double index_of_dispersion(MeanStddevPair const &ms)
Calculate the index of dispersion.
Definition: statistics.hpp:844
std::shared_ptr< BaseOutputTarget > to_string(std::string &target_string)
Obtain an output target for writing to a string.
Store the values of quartiles: q0 == min, q1 == 25%, q2 == 50%, q3 == 75%, q4 == max.
Definition: statistics.hpp:127
double spearmans_rank_correlation_coefficient(RandomAccessIteratorA first_a, RandomAccessIteratorA last_a, RandomAccessIteratorB first_b, RandomAccessIteratorB last_b)
Calculate Spearman&#39;s Rank Correlation Coefficient between two ranges of double.
Definition: statistics.hpp:964
MinMaxPair< double > finite_minimum_maximum(ForwardIterator first, ForwardIterator last)
Return the minimum and the maximum of a range of double values.
Definition: statistics.hpp:239
double finite_maximum(ForwardIterator first, ForwardIterator last)
Return the maximum of a range of double values.
Definition: statistics.hpp:207
std::pair< size_t, size_t > count_finite_elements(ForwardIterator first, ForwardIterator last)
Count the number of finite elements in a range of double values.
Definition: statistics.hpp:150
MeanStddevPair mean_stddev(ForwardIterator first, ForwardIterator last, double epsilon=-1.0)
Calculate the arithmetic mean and standard deviation of a range of double elements.
Definition: statistics.hpp:358