38 const std::vector<std::vector<double>>& data)
43 std::size_t n = data.size();
44 std::size_t p = data[0].size();
47 throw std::invalid_argument(
"statcpp::covariance_matrix: need at least 2 observations");
51 std::vector<double> means(p, 0.0);
52 for (std::size_t j = 0; j < p; ++j) {
53 for (std::size_t i = 0; i < n; ++i) {
54 means[j] += data[i][j];
56 means[j] /=
static_cast<double>(n);
60 std::vector<std::vector<double>> cov(p, std::vector<double>(p, 0.0));
61 for (std::size_t j1 = 0; j1 < p; ++j1) {
62 for (std::size_t j2 = j1; j2 < p; ++j2) {
64 for (std::size_t i = 0; i < n; ++i) {
65 sum += (data[i][j1] - means[j1]) * (data[i][j2] - means[j2]);
67 cov[j1][j2] =
sum /
static_cast<double>(n - 1);
68 cov[j2][j1] = cov[j1][j2];
90 const std::vector<std::vector<double>>& data)
95 std::size_t n = data.size();
96 std::size_t p = data[0].size();
99 throw std::invalid_argument(
"statcpp::correlation_matrix: need at least 2 observations");
106 std::vector<double> stddevs(p);
107 for (std::size_t j = 0; j < p; ++j) {
108 stddevs[j] = std::sqrt(cov[j][j]);
109 if (stddevs[j] == 0.0) {
110 throw std::invalid_argument(
"statcpp::correlation_matrix: zero variance variable");
115 std::vector<std::vector<double>> corr(p, std::vector<double>(p, 0.0));
116 for (std::size_t j1 = 0; j1 < p; ++j1) {
117 for (std::size_t j2 = 0; j2 < p; ++j2) {
118 corr[j1][j2] = cov[j1][j2] / (stddevs[j1] * stddevs[j2]);
140 const std::vector<std::vector<double>>& data)
145 std::size_t n = data.size();
146 std::size_t p = data[0].size();
149 throw std::invalid_argument(
"statcpp::standardize: need at least 2 observations");
153 std::vector<double> means(p, 0.0);
154 std::vector<double> stddevs(p, 0.0);
156 for (std::size_t j = 0; j < p; ++j) {
157 for (std::size_t i = 0; i < n; ++i) {
158 means[j] += data[i][j];
160 means[j] /=
static_cast<double>(n);
162 for (std::size_t i = 0; i < n; ++i) {
163 double diff = data[i][j] - means[j];
166 stddevs[j] = std::sqrt(stddevs[j] /
static_cast<double>(n - 1));
168 if (stddevs[j] == 0.0) {
169 throw std::invalid_argument(
"statcpp::standardize: zero variance variable");
174 std::vector<std::vector<double>> result(n, std::vector<double>(p));
175 for (std::size_t i = 0; i < n; ++i) {
176 for (std::size_t j = 0; j < p; ++j) {
177 result[i][j] = (data[i][j] - means[j]) / stddevs[j];
199 const std::vector<std::vector<double>>& data)
204 std::size_t n = data.size();
205 std::size_t p = data[0].size();
208 std::vector<double> mins(p, std::numeric_limits<double>::max());
209 std::vector<double> maxs(p, std::numeric_limits<double>::lowest());
211 for (std::size_t j = 0; j < p; ++j) {
212 for (std::size_t i = 0; i < n; ++i) {
213 mins[j] = std::min(mins[j], data[i][j]);
214 maxs[j] = std::max(maxs[j], data[i][j]);
217 if (maxs[j] == mins[j]) {
218 throw std::invalid_argument(
"statcpp::min_max_scale: zero range variable");
223 std::vector<std::vector<double>> result(n, std::vector<double>(p));
224 for (std::size_t i = 0; i < n; ++i) {
225 for (std::size_t j = 0; j < p; ++j) {
226 result[i][j] = (data[i][j] - mins[j]) / (maxs[j] - mins[j]);
260 const std::vector<std::vector<double>>& matrix,
261 std::size_t max_iter = 1000,
264 std::size_t n = matrix.size();
265 std::vector<double> v(n, 1.0 / std::sqrt(
static_cast<double>(n)));
267 double eigenvalue = 0.0;
269 for (std::size_t iter = 0; iter < max_iter; ++iter) {
271 std::vector<double> Av(n, 0.0);
272 for (std::size_t i = 0; i < n; ++i) {
273 for (std::size_t j = 0; j < n; ++j) {
274 Av[i] += matrix[i][j] * v[j];
280 for (std::size_t i = 0; i < n; ++i) {
281 norm += Av[i] * Av[i];
283 norm = std::sqrt(norm);
285 if (norm == 0.0)
break;
288 double new_eigenvalue = 0.0;
289 for (std::size_t i = 0; i < n; ++i) {
290 new_eigenvalue += v[i] * Av[i];
294 for (std::size_t i = 0; i < n; ++i) {
299 if (std::abs(new_eigenvalue - eigenvalue) < tol) {
300 eigenvalue = new_eigenvalue;
303 eigenvalue = new_eigenvalue;
306 return {eigenvalue, v};
326 std::size_t n_components)
331 std::size_t p = data[0].size();
333 if (n_components > p) {
341 result.
components.resize(p, std::vector<double>(n_components));
346 double total_variance = 0.0;
347 for (std::size_t j = 0; j < p; ++j) {
348 total_variance += cov[j][j];
352 auto working_cov = cov;
354 for (std::size_t k = 0; k < n_components; ++k) {
360 for (std::size_t j = 0; j < p; ++j) {
365 for (std::size_t i = 0; i < p; ++i) {
366 for (std::size_t j = 0; j < p; ++j) {
367 working_cov[i][j] -= eigenvalue * eigenvector[i] * eigenvector[j];
386 const std::vector<std::vector<double>>& data,
394 throw std::invalid_argument(
"statcpp::pca_transform: pca.components is empty");
397 std::size_t n = data.size();
398 std::size_t p = data[0].size();
403 throw std::invalid_argument(
"statcpp::pca_transform: dimension mismatch between data and pca.components");
407 std::vector<double> means(p, 0.0);
408 for (std::size_t j = 0; j < p; ++j) {
409 for (std::size_t i = 0; i < n; ++i) {
410 means[j] += data[i][j];
412 means[j] /=
static_cast<double>(n);
416 std::vector<std::vector<double>> result(n, std::vector<double>(n_components, 0.0));
417 for (std::size_t i = 0; i < n; ++i) {
418 for (std::size_t k = 0; k < n_components; ++k) {
419 for (std::size_t j = 0; j < p; ++j) {
420 result[i][k] += (data[i][j] - means[j]) *
pca.
components[j][k];
Linear regression analysis.
void validate_matrix_structure(const std::vector< std::vector< double > > &data, const char *func_name)
Validate 2D matrix structure.
std::vector< std::vector< double > > min_max_scale(const std::vector< std::vector< double > > &data)
Min-Max normalization (0-1 scaling)
auto sum(Iterator first, Iterator last)
Sum.
std::vector< std::vector< double > > standardize(const std::vector< std::vector< double > > &data)
Z-score standardization.
std::pair< double, std::vector< double > > power_iteration(const std::vector< std::vector< double > > &matrix, std::size_t max_iter=1000, double tol=1e-10)
Find largest eigenvalue and eigenvector using power iteration.
std::vector< double > diff(Iterator first, Iterator last, std::size_t order=1)
Difference series (first-order or d-th order differencing)
std::vector< std::vector< double > > covariance_matrix(const std::vector< std::vector< double > > &data)
Calculate sample covariance matrix.
std::vector< std::vector< double > > correlation_matrix(const std::vector< std::vector< double > > &data)
Calculate Pearson correlation matrix.
pca_result pca(const std::vector< std::vector< double > > &data, std::size_t n_components)
Principal Component Analysis.
std::vector< std::vector< double > > pca_transform(const std::vector< std::vector< double > > &data, const pca_result &pca)
Project data onto principal component space.
std::vector< std::vector< double > > components
Principal components (eigenvectors) p x n_components.
std::vector< double > explained_variance
Explained variance (eigenvalues)
std::vector< double > explained_variance_ratio
Variance explained ratio.