44template <
typename Iterator>
47 auto n =
static_cast<std::size_t
>(std::distance(first, last));
49 throw std::invalid_argument(
"statcpp::autocorrelation: empty range");
52 throw std::invalid_argument(
"statcpp::autocorrelation: lag must be less than n");
62 for (
auto it = first; it != last; ++it) {
63 double diff =
static_cast<double>(*it) - m;
68 throw std::invalid_argument(
"statcpp::autocorrelation: zero variance");
75 std::advance(it2,
lag);
77 for (std::size_t i = 0; i < n -
lag; ++i) {
78 cov += (
static_cast<double>(*it1) - m) * (
static_cast<double>(*it2) - m);
96template <
typename Iterator>
97std::vector<double>
acf(Iterator first, Iterator last, std::size_t max_lag)
99 auto n =
static_cast<std::size_t
>(std::distance(first, last));
101 throw std::invalid_argument(
"statcpp::acf: empty range");
107 std::vector<double> result;
108 result.reserve(max_lag + 1);
110 for (std::size_t
lag = 0;
lag <= max_lag; ++
lag) {
133template <
typename Iterator>
134std::vector<double>
pacf(Iterator first, Iterator last, std::size_t max_lag)
136 auto n =
static_cast<std::size_t
>(std::distance(first, last));
138 throw std::invalid_argument(
"statcpp::pacf: empty range");
145 auto r =
acf(first, last, max_lag);
147 std::vector<double> result;
148 result.reserve(max_lag + 1);
149 result.push_back(1.0);
151 if (max_lag == 0)
return result;
154 std::vector<double> phi(max_lag + 1);
155 std::vector<double> phi_prev(max_lag + 1);
158 result.push_back(r[1]);
161 for (std::size_t k = 2; k <= max_lag; ++k) {
166 for (std::size_t j = 1; j < k; ++j) {
167 num -= phi_prev[j] * r[k - j];
168 den -= phi_prev[j] * r[j];
171 if (std::abs(den) < 1e-15) {
178 for (std::size_t j = 1; j < k; ++j) {
179 phi[j] = phi_prev[j] - phi[k] * phi_prev[k - j];
182 result.push_back(phi[k]);
206template <
typename Iterator1,
typename Iterator2>
207double mae(Iterator1 first1, Iterator1 last1, Iterator2 first2)
209 auto n =
static_cast<std::size_t
>(std::distance(first1, last1));
211 throw std::invalid_argument(
"statcpp::mae: empty range");
216 for (
auto it1 = first1; it1 != last1; ++it1, ++it2) {
217 sum += std::abs(
static_cast<double>(*it1) -
static_cast<double>(*it2));
220 return sum /
static_cast<double>(n);
236template <
typename Iterator1,
typename Iterator2>
237double mse(Iterator1 first1, Iterator1 last1, Iterator2 first2)
239 auto n =
static_cast<std::size_t
>(std::distance(first1, last1));
241 throw std::invalid_argument(
"statcpp::mse: empty range");
246 for (
auto it1 = first1; it1 != last1; ++it1, ++it2) {
247 double diff =
static_cast<double>(*it1) -
static_cast<double>(*it2);
251 return sum /
static_cast<double>(n);
265template <
typename Iterator1,
typename Iterator2>
266double rmse(Iterator1 first1, Iterator1 last1, Iterator2 first2)
268 return std::sqrt(
mse(first1, last1, first2));
284template <
typename Iterator1,
typename Iterator2>
285double mape(Iterator1 first1, Iterator1 last1, Iterator2 first2)
287 auto n =
static_cast<std::size_t
>(std::distance(first1, last1));
289 throw std::invalid_argument(
"statcpp::mape: empty range");
293 std::size_t valid_count = 0;
295 for (
auto it1 = first1; it1 != last1; ++it1, ++it2) {
296 double actual =
static_cast<double>(*it1);
298 double predicted =
static_cast<double>(*it2);
299 sum += std::abs((actual - predicted) / actual);
304 if (valid_count == 0) {
305 throw std::invalid_argument(
"statcpp::mape: all actual values are zero");
308 return sum /
static_cast<double>(valid_count) * 100.0;
327template <
typename Iterator>
328std::vector<double>
moving_average(Iterator first, Iterator last, std::size_t window)
330 auto n =
static_cast<std::size_t
>(std::distance(first, last));
332 throw std::invalid_argument(
"statcpp::moving_average: empty range");
334 if (window == 0 || window > n) {
335 throw std::invalid_argument(
"statcpp::moving_average: invalid window size");
338 std::vector<double> data;
340 for (
auto it = first; it != last; ++it) {
341 data.push_back(
static_cast<double>(*it));
344 std::vector<double> result;
345 result.reserve(n - window + 1);
348 for (std::size_t i = 0; i < window; ++i) {
351 result.push_back(
sum /
static_cast<double>(window));
353 for (std::size_t i = window; i < n; ++i) {
354 sum += data[i] - data[i - window];
355 result.push_back(
sum /
static_cast<double>(window));
373template <
typename Iterator>
376 auto n =
static_cast<std::size_t
>(std::distance(first, last));
378 throw std::invalid_argument(
"statcpp::exponential_moving_average: empty range");
380 if (alpha <= 0.0 || alpha > 1.0) {
381 throw std::invalid_argument(
"statcpp::exponential_moving_average: alpha must be in (0, 1]");
384 std::vector<double> result;
388 double ema =
static_cast<double>(*it);
389 result.push_back(ema);
392 for (; it != last; ++it) {
393 ema = alpha *
static_cast<double>(*it) + (1.0 - alpha) * ema;
394 result.push_back(ema);
416template <
typename Iterator>
417std::vector<double>
diff(Iterator first, Iterator last, std::size_t order = 1)
419 auto n =
static_cast<std::size_t
>(std::distance(first, last));
421 throw std::invalid_argument(
"statcpp::diff: insufficient data for differencing order");
424 std::vector<double> data;
426 for (
auto it = first; it != last; ++it) {
427 data.push_back(
static_cast<double>(*it));
430 for (std::size_t d = 0; d < order; ++d) {
431 std::vector<double> new_data;
432 new_data.reserve(data.size() - 1);
433 for (std::size_t i = 1; i < data.size(); ++i) {
434 new_data.push_back(data[i] - data[i - 1]);
436 data = std::move(new_data);
454template <
typename Iterator>
455std::vector<double>
seasonal_diff(Iterator first, Iterator last, std::size_t period)
458 throw std::invalid_argument(
"statcpp::seasonal_diff: period must be positive");
461 auto n =
static_cast<std::size_t
>(std::distance(first, last));
463 throw std::invalid_argument(
"statcpp::seasonal_diff: insufficient data for period");
466 std::vector<double> data;
468 for (
auto it = first; it != last; ++it) {
469 data.push_back(
static_cast<double>(*it));
472 std::vector<double> result;
473 result.reserve(n - period);
475 for (std::size_t i = period; i < n; ++i) {
476 result.push_back(data[i] - data[i - period]);
498template <
typename Iterator>
499std::vector<double>
lag(Iterator first, Iterator last, std::size_t k)
501 auto n =
static_cast<std::size_t
>(std::distance(first, last));
503 throw std::invalid_argument(
"statcpp::lag: lag exceeds data length");
506 std::vector<double> result;
507 result.reserve(n - k);
510 for (std::size_t i = 0; i < n - k; ++i, ++it) {
511 result.push_back(
static_cast<double>(*it));
Basic statistical computation functions.
double rmse(Iterator1 first1, Iterator1 last1, Iterator2 first2)
Root Mean Squared Error (RMSE)
auto sum(Iterator first, Iterator last)
Sum.
double var(Iterator first, Iterator last, std::size_t ddof=0)
Variance (ddof = Delta Degrees of Freedom)
double mae(Iterator1 first1, Iterator1 last1, Iterator2 first2)
Mean Absolute Error (MAE)
std::vector< double > seasonal_diff(Iterator first, Iterator last, std::size_t period)
Seasonal differencing.
double mape(Iterator1 first1, Iterator1 last1, Iterator2 first2)
Mean Absolute Percentage Error (MAPE)
double mean(Iterator first, Iterator last)
Arithmetic mean.
double autocorrelation(Iterator first, Iterator last, std::size_t lag)
Calculate autocorrelation coefficient (lag k)
std::vector< double > lag(Iterator first, Iterator last, std::size_t k)
Generate lag series.
std::vector< double > diff(Iterator first, Iterator last, std::size_t order=1)
Difference series (first-order or d-th order differencing)
std::vector< double > pacf(Iterator first, Iterator last, std::size_t max_lag)
Calculate partial autocorrelation function (PACF) (Durbin-Levinson algorithm)
std::vector< double > acf(Iterator first, Iterator last, std::size_t max_lag)
Calculate autocorrelation function (ACF) (from lag 0 to max_lag)
double mse(Iterator1 first1, Iterator1 last1, Iterator2 first2)
Mean Squared Error (MSE)
std::vector< double > moving_average(Iterator first, Iterator last, std::size_t window)
Simple moving average.
std::vector< double > exponential_moving_average(Iterator first, Iterator last, double alpha)
Exponential moving average.