v2.0.0
Loading...
Searching...
No Matches
sts_ftest.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
39#include "sts_ftest.h"
40#include "sts_ttest.h"
41
42#include <cmath>
43
44//=============================================================================================================
45// USED NAMESPACES
46//=============================================================================================================
47
48using namespace STSLIB;
49using namespace Eigen;
50
51//=============================================================================================================
52// DEFINE METHODS
53//=============================================================================================================
54
55StatsFtestResult StatsFtest::oneWay(const QVector<MatrixXd>& groups)
56{
57 const int k = groups.size();
58 const int nVars = static_cast<int>(groups[0].cols());
59
60 // Total number of observations
61 int N = 0;
62 for (int g = 0; g < k; ++g) {
63 N += static_cast<int>(groups[g].rows());
64 }
65
66 // Grand mean
67 RowVectorXd grandMean = RowVectorXd::Zero(nVars);
68 for (int g = 0; g < k; ++g) {
69 grandMean += groups[g].colwise().sum();
70 }
71 grandMean /= static_cast<double>(N);
72
73 // Between-group sum of squares and within-group sum of squares
74 RowVectorXd ssBetween = RowVectorXd::Zero(nVars);
75 RowVectorXd ssWithin = RowVectorXd::Zero(nVars);
76
77 for (int g = 0; g < k; ++g) {
78 int ng = static_cast<int>(groups[g].rows());
79 RowVectorXd groupMean = groups[g].colwise().mean();
80
81 // Between: n_g * (groupMean - grandMean)^2
82 RowVectorXd diff = groupMean - grandMean;
83 ssBetween += static_cast<double>(ng) * diff.array().square().matrix();
84
85 // Within: sum of (x_i - groupMean)^2
86 MatrixXd centered = groups[g].rowwise() - groupMean;
87 ssWithin += centered.colwise().squaredNorm();
88 }
89
90 int dfBetween = k - 1;
91 int dfWithin = N - k;
92
93 RowVectorXd msBetween = ssBetween / static_cast<double>(dfBetween);
94 RowVectorXd msWithin = ssWithin / static_cast<double>(dfWithin);
95
96 // F-statistic
97 RowVectorXd fstat = msBetween.array() / msWithin.array();
98
99 // p-values
100 MatrixXd matPval(1, nVars);
101 for (int j = 0; j < nVars; ++j) {
102 matPval(0, j) = 1.0 - fCdf(fstat(j), dfBetween, dfWithin);
103 }
104
105 StatsFtestResult result;
106 result.matFstat = fstat;
107 result.matPval = matPval;
108 result.dfBetween = dfBetween;
109 result.dfWithin = dfWithin;
110 return result;
111}
112
113//=============================================================================================================
114
115double StatsFtest::fCdf(double f, int df1, int df2)
116{
117 // P(F <= f) using the relationship to the regularized incomplete beta function:
118 // P(F <= f) = I_x(df1/2, df2/2) where x = df1*f / (df1*f + df2)
119 if (f <= 0.0) return 0.0;
120
121 double x = static_cast<double>(df1) * f / (static_cast<double>(df1) * f + static_cast<double>(df2));
122 double a = static_cast<double>(df1) / 2.0;
123 double b = static_cast<double>(df2) / 2.0;
124
125 // Reuse the regularized beta function from StatsTtest
126 return StatsTtest::regularizedBeta(x, a, b);
127}
StatsTtest class declaration.
StatsFtest class declaration.
Statistical testing (t-tests, F-tests, cluster permutation, multiple comparison correction).
Eigen::MatrixXd matFstat
Definition sts_ftest.h:68
Eigen::MatrixXd matPval
Definition sts_ftest.h:69
static double fCdf(double f, int df1, int df2)
static StatsFtestResult oneWay(const QVector< Eigen::MatrixXd > &groups)
Definition sts_ftest.cpp:55
static double regularizedBeta(double x, double a, double b)