47 const int n =
static_cast<int>(data.rows());
48 const int nVars =
static_cast<int>(data.cols());
52 RowVectorXd means = data.colwise().mean();
55 MatrixXd centered = data.rowwise() - means;
56 RowVectorXd stddev = (centered.colwise().squaredNorm() /
static_cast<double>(df)).array().sqrt();
59 double sqrtN = std::sqrt(
static_cast<double>(n));
60 RowVectorXd tstat = (means.array() - mu) / (stddev.array() / sqrtN);
63 MatrixXd matPval(1, nVars);
64 for (
int j = 0; j < nVars; ++j) {
65 matPval(0, j) = tToPval(tstat(j), df, tail);
79 return oneSample(dataA - dataB, 0.0, tail);
86 const int nA =
static_cast<int>(dataA.rows());
87 const int nB =
static_cast<int>(dataB.rows());
88 const int nVars =
static_cast<int>(dataA.cols());
89 const int df = nA + nB - 2;
91 RowVectorXd meanA = dataA.colwise().mean();
92 RowVectorXd meanB = dataB.colwise().mean();
95 MatrixXd centA = dataA.rowwise() - meanA;
96 MatrixXd centB = dataB.rowwise() - meanB;
97 RowVectorXd ssA = centA.colwise().squaredNorm();
98 RowVectorXd ssB = centB.colwise().squaredNorm();
99 RowVectorXd pooledVar = (ssA + ssB) /
static_cast<double>(df);
102 double invN = 1.0 /
static_cast<double>(nA) + 1.0 /
static_cast<double>(nB);
103 RowVectorXd tstat = (meanA - meanB).array() / (pooledVar.array() * invN).sqrt();
106 MatrixXd matPval(1, nVars);
107 for (
int j = 0; j < nVars; ++j) {
108 matPval(0, j) = tToPval(tstat(j), df, tail);
125 double x =
static_cast<double>(df) / (
static_cast<double>(df) + t * t);
128 return 1.0 - 0.5 * iBeta;
136double StatsTtest::tToPval(
double t,
int df,
StatsTailType tail)
138 double cdf =
tCdf(t, df);
146 return 2.0 * std::min(cdf, 1.0 - cdf);
157 if (x <= 0.0)
return 0.0;
158 if (x >= 1.0)
return 1.0;
160 if (x > (a + 1.0) / (a + b + 2.0)) {
164 double lnPre = a * std::log(x) + b * std::log(1.0 - x) - logBeta(a, b) - std::log(a);
165 return std::exp(lnPre) * betaCf(x, a, b);
170double StatsTtest::betaCf(
double x,
double a,
double b)
173 const int maxIter = 200;
174 const double eps = 1.0e-12;
175 const double tiny = 1.0e-30;
178 double qap = a + 1.0;
179 double qam = a - 1.0;
182 double d = 1.0 - qab * x / qap;
183 if (std::fabs(d) < tiny) d = tiny;
187 for (
int m = 1; m <= maxIter; ++m) {
191 double aa = m * (b - m) * x / ((qam + m2) * (a + m2));
193 if (std::fabs(d) < tiny) d = tiny;
195 if (std::fabs(c) < tiny) c = tiny;
200 aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
202 if (std::fabs(d) < tiny) d = tiny;
204 if (std::fabs(c) < tiny) c = tiny;
209 if (std::fabs(del - 1.0) < eps)
break;
216double StatsTtest::logBeta(
double a,
double b)
218 return std::lgamma(a) + std::lgamma(b) - std::lgamma(a + b);
Frequentist Student's t-tests with exact p-values via the regularised incomplete beta function.
Statistical testing (t-tests, F-tests, cluster permutation, multiple comparison correction).
StatsTailType
Direction of the alternative hypothesis for a t- or F-test (left, right, or two-sided).
Per-call output of a Student t-test: t-statistics, p-values and degrees of freedom.
static double regularizedBeta(double x, double a, double b)
static StatsTtestResult paired(const Eigen::MatrixXd &dataA, const Eigen::MatrixXd &dataB, StatsTailType tail=StatsTailType::Both)
static double tCdf(double t, int df)
static StatsTtestResult oneSample(const Eigen::MatrixXd &data, double mu=0.0, StatsTailType tail=StatsTailType::Both)
static StatsTtestResult independent(const Eigen::MatrixXd &dataA, const Eigen::MatrixXd &dataB, StatsTailType tail=StatsTailType::Both)