LCOV - code coverage report
Current view: top level - modules/stats - describe.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 124 163 76.1 %
Date: 2024-05-13 05:06:06 Functions: 22 27 81.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*************************************************************************
       2             :  *
       3             :  *  Project
       4             :  *                         _____ _____  __  __ _____
       5             :  *                        / ____|  __ \|  \/  |  __ \
       6             :  *  ___  _ __   ___ _ __ | |  __| |__) | \  / | |__) |
       7             :  * / _ \| '_ \ / _ \ '_ \| | |_ |  ___/| |\/| |  ___/
       8             :  *| (_) | |_) |  __/ | | | |__| | |    | |  | | |
       9             :  * \___/| .__/ \___|_| |_|\_____|_|    |_|  |_|_|
      10             :  *      | |
      11             :  *      |_|
      12             :  *
      13             :  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
      14             :  *
      15             :  * This software is licensed as described in the file LICENSE, which
      16             :  * you should have received as part of this distribution. The terms
      17             :  * among other details are referenced in the official documentation
      18             :  * seen here : https://akielaries.github.io/openGPMP/ along with
      19             :  * important files seen in this project.
      20             :  *
      21             :  * You may opt to use, copy, modify, merge, publish, distribute
      22             :  * and/or sell copies of the Software, and permit persons to whom
      23             :  * the Software is furnished to do so, under the terms of the
      24             :  * LICENSE file. As this is an Open Source effort, all implementations
      25             :  * must be of the same methodology.
      26             :  *
      27             :  *
      28             :  *
      29             :  * This software is distributed on an AS IS basis, WITHOUT
      30             :  * WARRANTY OF ANY KIND, either express or implied.
      31             :  *
      32             :  ************************************************************************/
      33             : #include <algorithm>
      34             : #include <cmath>
      35             : #include <openGPMP/stats/describe.hpp>
      36             : #include <vector>
      37             : 
      38           0 : double gpmp::stats::Describe::u_stat(const std::vector<double> &sample1,
      39             :                                      const std::vector<double> &sample2) {
      40           0 :     double U = 0;
      41           0 :     for (double x1 : sample1) {
      42           0 :         for (double x2 : sample2) {
      43           0 :             if (x1 < x2) {
      44           0 :                 U++;
      45             :             }
      46             :         }
      47             :     }
      48           0 :     return U;
      49             : }
      50             : 
      51             : // Arithmetic Mean
      52          17 : double gpmp::stats::Describe::mean_arith(const std::vector<double> &data) {
      53          17 :     double sum = 0.0;
      54          83 :     for (const auto &value : data) {
      55          66 :         sum += value;
      56             :     }
      57          17 :     return sum / static_cast<double>(data.size());
      58             : }
      59             : 
      60             : // Geometric Mean
      61           2 : double gpmp::stats::Describe::mean_geo(const std::vector<double> &data) {
      62           2 :     double product = 1.0;
      63           6 :     for (const auto &value : data) {
      64           4 :         product *= value;
      65             :     }
      66           2 :     return std::pow(product, 1.0 / static_cast<double>(data.size()));
      67             : }
      68             : 
      69             : // Cubic Generalized Mean
      70           4 : double gpmp::stats::Describe::mean_cubic(const std::vector<double> &data,
      71             :                                          double p) {
      72           4 :     double sum = 0.0;
      73          15 :     for (const auto &value : data) {
      74          11 :         sum += std::pow(value, p);
      75             :     }
      76           4 :     return std::pow(sum / static_cast<double>(data.size()), 1.0 / p);
      77             : }
      78             : 
      79             : // Power Geometric Mean
      80           1 : double gpmp::stats::Describe::mean_geo_pow(const std::vector<double> &data,
      81             :                                            double p) {
      82           1 :     double product = 1.0;
      83           2 :     for (const auto &value : data) {
      84           1 :         product *= std::pow(value, p);
      85             :     }
      86           1 :     return std::pow(product, 1.0 / static_cast<double>(data.size()));
      87             : }
      88             : 
      89             : // Harmonic Mean
      90           2 : double gpmp::stats::Describe::mean_harmonic(const std::vector<double> &data) {
      91           2 :     double sum = 0.0;
      92           6 :     for (const auto &value : data) {
      93           4 :         sum += 1.0 / value;
      94             :     }
      95           2 :     return static_cast<double>(data.size()) / sum;
      96             : }
      97             : 
      98             : // Heronian Mean
      99           1 : double gpmp::stats::Describe::mean_heronian(const std::vector<double> &data) {
     100           1 :     double product = 1.0;
     101           2 :     for (const auto &value : data) {
     102           1 :         product *= std::sqrt(value);
     103             :     }
     104           1 :     return std::pow(product, 2.0 / static_cast<double>(data.size()));
     105             : }
     106             : 
     107             : // Heinz Mean
     108           0 : double gpmp::stats::Describe::mean_heinz(const std::vector<double> &data) {
     109           0 :     double sum = 0.0;
     110           0 :     for (const auto &value : data) {
     111           0 :         sum += value * std::log(value);
     112             :     }
     113           0 :     return std::exp(sum / static_cast<double>(data.size()));
     114             : }
     115             : 
     116             : // Lehmer Mean
     117           1 : double gpmp::stats::Describe::mean_lehmer(const std::vector<double> &data,
     118             :                                           double p) {
     119           1 :     double sum = 0.0;
     120           2 :     for (const auto &value : data) {
     121           1 :         sum += std::pow(value, p);
     122             :     }
     123           1 :     return sum / static_cast<double>(data.size());
     124             : }
     125             : 
     126             : // Median
     127           2 : double gpmp::stats::Describe::Median(std::vector<double> data) {
     128           2 :     std::sort(data.begin(), data.end());
     129           2 :     size_t size = data.size();
     130           2 :     if (size % 2 == 0) {
     131           1 :         return (data[size / 2 - 1] + data[size / 2]) / 2.0;
     132             :     } else {
     133           1 :         return data[size / 2];
     134             :     }
     135             : }
     136             : 
     137             : // Average Absolute Deviation
     138           2 : double gpmp::stats::Describe::avg_abs_dev(const std::vector<double> &data) {
     139           2 :     double mean = mean_arith(data);
     140           2 :     double sum = 0.0;
     141           7 :     for (const auto &value : data) {
     142           5 :         sum += std::abs(value - mean);
     143             :     }
     144           2 :     return sum / static_cast<double>(data.size());
     145             : }
     146             : 
     147             : // Coefficient of Variation
     148           2 : double gpmp::stats::Describe::var_coeff(const std::vector<double> &data) {
     149           2 :     double mean = mean_arith(data);
     150           2 :     double stddev = stdev(data, mean);
     151           2 :     return (stddev / mean) * 100.0; // Multiply by 100 for percentage
     152             : }
     153             : 
     154             : // Interquartile Range
     155           1 : double gpmp::stats::Describe::iq_range(const std::vector<double> &data) {
     156           1 :     std::vector<double> sortedData = data;
     157           1 :     std::sort(sortedData.begin(), sortedData.end());
     158             : 
     159           1 :     size_t size = sortedData.size();
     160           1 :     size_t lowerIndex = size / 4;
     161           1 :     size_t upperIndex = 3 * size / 4;
     162             : 
     163           2 :     return sortedData[upperIndex] - sortedData[lowerIndex];
     164           1 : }
     165             : 
     166             : // percentile
     167           1 : double gpmp::stats::Describe::percentile(const std::vector<double> &data,
     168             :                                          double percentile) {
     169           1 :     std::vector<double> sortedData = data;
     170           1 :     std::sort(sortedData.begin(), sortedData.end());
     171             : 
     172           1 :     size_t size = sortedData.size();
     173           1 :     size_t index = static_cast<size_t>(percentile * (size - 1));
     174           2 :     return sortedData[index];
     175           1 : }
     176             : 
     177             : // Range
     178           1 : double gpmp::stats::Describe::range(const std::vector<double> &data) {
     179           1 :     auto result = std::minmax_element(data.begin(), data.end());
     180           1 :     return *result.second - *result.first;
     181             : }
     182             : 
     183             : // Standard Deviation
     184           7 : double gpmp::stats::Describe::stdev(const std::vector<double> &data,
     185             :                                     double mean) {
     186           7 :     double sum = 0.0;
     187          32 :     for (const auto &value : data) {
     188          25 :         sum += std::pow(value - mean, 2.0);
     189             :     }
     190           7 :     return std::sqrt(sum / static_cast<double>(data.size()));
     191             : }
     192             : 
     193             : // variance
     194           3 : double gpmp::stats::Describe::variance(const std::vector<double> &data,
     195             :                                        double mean) {
     196           3 :     double sum = 0.0;
     197          13 :     for (const auto &value : data) {
     198          10 :         sum += std::pow(value - mean, 2.0);
     199             :     }
     200           3 :     return sum / static_cast<double>(data.size());
     201             : }
     202             : 
     203             : // central limit theorem
     204           1 : double gpmp::stats::Describe::clt(const std::vector<double> &data,
     205             :                                   int numSamples) {
     206           1 :     double mean = mean_arith(data);
     207           1 :     double stddev = stdev(data, mean);
     208           1 :     return stddev / std::sqrt(static_cast<double>(numSamples));
     209             : }
     210             : 
     211             : // Kurtosis
     212           1 : double gpmp::stats::Describe::kurtosis(const std::vector<double> &data,
     213             :                                        double mean) {
     214           1 :     double sum = 0.0;
     215           6 :     for (const auto &value : data) {
     216           5 :         sum += std::pow(value - mean, 4.0);
     217             :     }
     218           1 :     double var = variance(data, mean);
     219           1 :     return sum / (data.size() * std::pow(var, 2.0)) - 3.0;
     220             : }
     221             : 
     222             : // l-moments (first two)
     223           1 : double gpmp::stats::Describe::lmoment1(const std::vector<double> &data,
     224             :                                        double mean) {
     225           1 :     double sum = 0.0;
     226           6 :     for (const auto &value : data) {
     227           5 :         sum += std::pow(value - mean, 3.0);
     228             :     }
     229           1 :     return sum / data.size();
     230             : }
     231             : 
     232           1 : double gpmp::stats::Describe::lmoment2(const std::vector<double> &data,
     233             :                                        double mean) {
     234           1 :     double sum = 0.0;
     235           6 :     for (const auto &value : data) {
     236           5 :         sum += std::pow(value - mean, 4.0);
     237             :     }
     238           1 :     return sum / data.size();
     239             : }
     240             : 
     241             : // skewness
     242           1 : double gpmp::stats::Describe::skewness(const std::vector<double> &data,
     243             :                                        double mean,
     244             :                                        double stddev) {
     245           1 :     double sum = 0.0;
     246           6 :     for (const auto &value : data) {
     247           5 :         sum += std::pow((value - mean) / stddev, 3.0);
     248             :     }
     249           1 :     return sum / static_cast<double>(data.size());
     250             : }
     251             : 
     252             : std::vector<size_t>
     253           1 : gpmp::stats::Describe::rank_data(const std::vector<double> &data) {
     254           1 :     std::vector<size_t> ranks(data.size());
     255             : 
     256           6 :     for (size_t i = 0; i < data.size(); ++i) {
     257           5 :         size_t rank = 1;
     258          30 :         for (size_t j = 0; j < data.size(); ++j) {
     259          25 :             if (j != i && data[j] < data[i]) {
     260          10 :                 rank++;
     261             :             }
     262             :         }
     263           5 :         ranks[i] = rank;
     264             :     }
     265             : 
     266           1 :     return ranks;
     267             : }
     268             : 
     269           0 : double gpmp::stats::Describe::partial_corr(const std::vector<double> &x,
     270             :                                            const std::vector<double> &y,
     271             :                                            const std::vector<double> &z) {
     272           0 :     double r_xy = ppmc(x, y);
     273           0 :     double r_xz = ppmc(x, z);
     274           0 :     double r_yz = ppmc(y, z);
     275             : 
     276           0 :     return (r_xy - (r_xz * r_yz)) /
     277           0 :            std::sqrt((1.0 - std::pow(r_xz, 2.0)) * (1.0 - std::pow(r_yz, 2.0)));
     278             : }
     279             : 
     280             : // Pearson Product-Moment Correlation
     281           1 : double gpmp::stats::Describe::ppmc(const std::vector<double> &x,
     282             :                                    const std::vector<double> &y) {
     283           1 :     double mean_x = mean_arith(x);
     284           1 :     double mean_y = mean_arith(y);
     285             : 
     286           1 :     double numerator = 0.0;
     287           1 :     double denominator_x = 0.0;
     288           1 :     double denominator_y = 0.0;
     289             : 
     290           6 :     for (size_t i = 0; i < x.size(); ++i) {
     291           5 :         numerator += (x[i] - mean_x) * (y[i] - mean_y);
     292           5 :         denominator_x += std::pow(x[i] - mean_x, 2.0);
     293           5 :         denominator_y += std::pow(y[i] - mean_y, 2.0);
     294             :     }
     295             : 
     296           1 :     return numerator / std::sqrt(denominator_x * denominator_y);
     297             : }
     298             : 
     299             : // Kendall's Tau Rank Correlation
     300           0 : double gpmp::stats::Describe::kendalls_tau(const std::vector<double> &x,
     301             :                                            const std::vector<double> &y) {
     302           0 :     size_t concordant = 0;
     303           0 :     size_t discordant = 0;
     304             : 
     305           0 :     for (size_t i = 0; i < x.size() - 1; ++i) {
     306           0 :         for (size_t j = i + 1; j < x.size(); ++j) {
     307           0 :             if ((x[i] < x[j] && y[i] < y[j]) || (x[i] > x[j] && y[i] > y[j])) {
     308           0 :                 concordant++;
     309           0 :             } else if ((x[i] < x[j] && y[i] > y[j]) ||
     310           0 :                        (x[i] > x[j] && y[i] < y[j])) {
     311           0 :                 discordant++;
     312             :             }
     313             :         }
     314             :     }
     315             : 
     316           0 :     return static_cast<double>(concordant - discordant) /
     317           0 :            std::sqrt(static_cast<double>((concordant + discordant) *
     318           0 :                                          (x.size() * (x.size() - 1)) / 2));
     319             : }
     320             : 
     321             : // Spearman's Rank Correlation
     322           0 : double gpmp::stats::Describe::spearmans_rho(const std::vector<double> &x,
     323             :                                             const std::vector<double> &y) {
     324           0 :     std::vector<size_t> ranks_x = rank_data(x);
     325           0 :     std::vector<size_t> ranks_y = rank_data(y);
     326             : 
     327           0 :     double d_squared = 0.0;
     328           0 :     for (size_t i = 0; i < x.size(); ++i) {
     329           0 :         d_squared += std::pow(ranks_x[i] - ranks_y[i], 2.0);
     330             :     }
     331             : 
     332             :     return 1.0 -
     333           0 :            (6.0 * d_squared) / (x.size() * (std::pow(x.size(), 2.0) - 1.0));
     334           0 : }

Generated by: LCOV version 1.14