statcpp
C++17 Header-Only Statistics Library
Loading...
Searching...
No Matches
estimation.hpp
Go to the documentation of this file.
1
9#pragma once
10
14
15#include <algorithm>
16#include <cmath>
17#include <cstddef>
18#include <stdexcept>
19
20namespace statcpp {
21
22// ============================================================================
23// Standard Error
24// ============================================================================
25
37template <typename Iterator>
38double standard_error(Iterator first, Iterator last)
39{
40 auto n = statcpp::count(first, last);
41 if (n < 2) {
42 throw std::invalid_argument("statcpp::standard_error: need at least 2 elements");
43 }
44 double s = statcpp::sample_stddev(first, last);
45 return s / std::sqrt(static_cast<double>(n));
46}
47
59template <typename Iterator, typename Projection>
60double standard_error(Iterator first, Iterator last, Projection proj)
61{
62 auto n = statcpp::count(first, last);
63 if (n < 2) {
64 throw std::invalid_argument("statcpp::standard_error: need at least 2 elements");
65 }
66 double s = statcpp::sample_stddev(first, last, proj);
67 return s / std::sqrt(static_cast<double>(n));
68}
69
80template <typename Iterator>
81double standard_error(Iterator first, Iterator last, double precomputed_stddev)
82{
83 auto n = statcpp::count(first, last);
84 if (n == 0) {
85 throw std::invalid_argument("statcpp::standard_error: empty range");
86 }
87 return precomputed_stddev / std::sqrt(static_cast<double>(n));
88}
89
90// ============================================================================
91// Confidence Interval Result Structure
92// ============================================================================
93
98 double lower;
99 double upper;
102};
103
104// ============================================================================
105// Confidence Interval for Mean (using t-distribution)
106// ============================================================================
107
118template <typename Iterator>
119confidence_interval ci_mean(Iterator first, Iterator last, double confidence = 0.95)
120{
121 if (confidence <= 0.0 || confidence >= 1.0) {
122 throw std::invalid_argument("statcpp::ci_mean: confidence must be in (0, 1)");
123 }
124
125 auto n = statcpp::count(first, last);
126 if (n < 2) {
127 throw std::invalid_argument("statcpp::ci_mean: need at least 2 elements");
128 }
129
130 double mean_val = statcpp::mean(first, last);
131 double se = statcpp::standard_error(first, last);
132 double df = static_cast<double>(n - 1);
133
134 double alpha = 1.0 - confidence;
135 double t_crit = t_quantile(1.0 - alpha / 2.0, df);
136
137 double margin = t_crit * se;
138
139 return {mean_val - margin, mean_val + margin, mean_val, confidence};
140}
141
154template <typename Iterator, typename Projection>
155confidence_interval ci_mean(Iterator first, Iterator last, double confidence, Projection proj)
156{
157 if (confidence <= 0.0 || confidence >= 1.0) {
158 throw std::invalid_argument("statcpp::ci_mean: confidence must be in (0, 1)");
159 }
160
161 auto n = statcpp::count(first, last);
162 if (n < 2) {
163 throw std::invalid_argument("statcpp::ci_mean: need at least 2 elements");
164 }
165
166 double mean_val = statcpp::mean(first, last, proj);
167 double se = statcpp::standard_error(first, last, proj);
168 double df = static_cast<double>(n - 1);
169
170 double alpha = 1.0 - confidence;
171 double t_crit = t_quantile(1.0 - alpha / 2.0, df);
172
173 double margin = t_crit * se;
174
175 return {mean_val - margin, mean_val + margin, mean_val, confidence};
176}
177
178// ============================================================================
179// Confidence Interval for Mean (using z-distribution, known variance)
180// ============================================================================
181
193template <typename Iterator>
194confidence_interval ci_mean_z(Iterator first, Iterator last, double sigma, double confidence = 0.95)
195{
196 if (confidence <= 0.0 || confidence >= 1.0) {
197 throw std::invalid_argument("statcpp::ci_mean_z: confidence must be in (0, 1)");
198 }
199 if (sigma <= 0.0) {
200 throw std::invalid_argument("statcpp::ci_mean_z: sigma must be positive");
201 }
202
203 auto n = statcpp::count(first, last);
204 if (n == 0) {
205 throw std::invalid_argument("statcpp::ci_mean_z: empty range");
206 }
207
208 double mean_val = statcpp::mean(first, last);
209 double se = sigma / std::sqrt(static_cast<double>(n));
210
211 double alpha = 1.0 - confidence;
212 double z_crit = norm_quantile(1.0 - alpha / 2.0);
213
214 double margin = z_crit * se;
215
216 return {mean_val - margin, mean_val + margin, mean_val, confidence};
217}
218
219// ============================================================================
220// Confidence Interval for Proportion
221// ============================================================================
222
232inline confidence_interval ci_proportion(std::size_t successes, std::size_t trials, double confidence = 0.95)
233{
234 if (confidence <= 0.0 || confidence >= 1.0) {
235 throw std::invalid_argument("statcpp::ci_proportion: confidence must be in (0, 1)");
236 }
237 if (trials == 0) {
238 throw std::invalid_argument("statcpp::ci_proportion: trials must be positive");
239 }
240 if (successes > trials) {
241 throw std::invalid_argument("statcpp::ci_proportion: successes cannot exceed trials");
242 }
243
244 double p_hat = static_cast<double>(successes) / static_cast<double>(trials);
245 double se = std::sqrt(p_hat * (1.0 - p_hat) / static_cast<double>(trials));
246
247 double alpha = 1.0 - confidence;
248 double z_crit = norm_quantile(1.0 - alpha / 2.0);
249
250 double margin = z_crit * se;
251 double lower = std::max(0.0, p_hat - margin);
252 double upper = std::min(1.0, p_hat + margin);
253
254 return {lower, upper, p_hat, confidence};
255}
256
269inline confidence_interval ci_proportion_wilson(std::size_t successes, std::size_t trials, double confidence = 0.95)
270{
271 if (confidence <= 0.0 || confidence >= 1.0) {
272 throw std::invalid_argument("statcpp::ci_proportion_wilson: confidence must be in (0, 1)");
273 }
274 if (trials == 0) {
275 throw std::invalid_argument("statcpp::ci_proportion_wilson: trials must be positive");
276 }
277 if (successes > trials) {
278 throw std::invalid_argument("statcpp::ci_proportion_wilson: successes cannot exceed trials");
279 }
280
281 double n = static_cast<double>(trials);
282 double p_hat = static_cast<double>(successes) / n;
283
284 double alpha = 1.0 - confidence;
285 double z = norm_quantile(1.0 - alpha / 2.0);
286 double z2 = z * z;
287
288 double denom = 1.0 + z2 / n;
289 double center = (p_hat + z2 / (2.0 * n)) / denom;
290 double margin = z * std::sqrt((p_hat * (1.0 - p_hat) + z2 / (4.0 * n)) / n) / denom;
291
292 return {center - margin, center + margin, p_hat, confidence};
293}
294
295// ============================================================================
296// Confidence Interval for Variance (Chi-square based)
297// ============================================================================
298
309template <typename Iterator>
310confidence_interval ci_variance(Iterator first, Iterator last, double confidence = 0.95)
311{
312 if (confidence <= 0.0 || confidence >= 1.0) {
313 throw std::invalid_argument("statcpp::ci_variance: confidence must be in (0, 1)");
314 }
315
316 auto n = statcpp::count(first, last);
317 if (n < 2) {
318 throw std::invalid_argument("statcpp::ci_variance: need at least 2 elements");
319 }
320
321 double var = statcpp::sample_variance(first, last);
322 double df = static_cast<double>(n - 1);
323
324 double alpha = 1.0 - confidence;
325 double chi2_lower = chisq_quantile(alpha / 2.0, df);
326 double chi2_upper = chisq_quantile(1.0 - alpha / 2.0, df);
327
328 double lower = df * var / chi2_upper;
329 double upper = df * var / chi2_lower;
330
331 return {lower, upper, var, confidence};
332}
333
334// ============================================================================
335// Confidence Interval for Difference of Means
336// ============================================================================
337
353template <typename Iterator1, typename Iterator2>
354confidence_interval ci_mean_diff(Iterator1 first1, Iterator1 last1,
355 Iterator2 first2, Iterator2 last2,
356 double confidence = 0.95)
357{
358 if (confidence <= 0.0 || confidence >= 1.0) {
359 throw std::invalid_argument("statcpp::ci_mean_diff: confidence must be in (0, 1)");
360 }
361
362 auto n1 = statcpp::count(first1, last1);
363 auto n2 = statcpp::count(first2, last2);
364
365 if (n1 < 2 || n2 < 2) {
366 throw std::invalid_argument("statcpp::ci_mean_diff: need at least 2 elements in each sample");
367 }
368
369 double mean1 = statcpp::mean(first1, last1);
370 double mean2 = statcpp::mean(first2, last2);
371 double var1 = statcpp::sample_variance(first1, last1);
372 double var2 = statcpp::sample_variance(first2, last2);
373
374 double diff = mean1 - mean2;
375
376 // Pooled variance
377 double df = static_cast<double>(n1 + n2 - 2);
378 double sp2 = ((n1 - 1) * var1 + (n2 - 1) * var2) / df;
379 double se = std::sqrt(sp2 * (1.0 / n1 + 1.0 / n2));
380
381 double alpha = 1.0 - confidence;
382 double t_crit = t_quantile(1.0 - alpha / 2.0, df);
383
384 double margin = t_crit * se;
385
386 return {diff - margin, diff + margin, diff, confidence};
387}
388
404template <typename Iterator1, typename Iterator2>
405confidence_interval ci_mean_diff_welch(Iterator1 first1, Iterator1 last1,
406 Iterator2 first2, Iterator2 last2,
407 double confidence = 0.95)
408{
409 if (confidence <= 0.0 || confidence >= 1.0) {
410 throw std::invalid_argument("statcpp::ci_mean_diff_welch: confidence must be in (0, 1)");
411 }
412
413 auto n1 = statcpp::count(first1, last1);
414 auto n2 = statcpp::count(first2, last2);
415
416 if (n1 < 2 || n2 < 2) {
417 throw std::invalid_argument("statcpp::ci_mean_diff_welch: need at least 2 elements in each sample");
418 }
419
420 double mean1 = statcpp::mean(first1, last1);
421 double mean2 = statcpp::mean(first2, last2);
422 double var1 = statcpp::sample_variance(first1, last1);
423 double var2 = statcpp::sample_variance(first2, last2);
424
425 double diff = mean1 - mean2;
426
427 double se1 = var1 / n1;
428 double se2 = var2 / n2;
429 double se = std::sqrt(se1 + se2);
430
431 // Welch-Satterthwaite approximation for degrees of freedom
432 double num = (se1 + se2) * (se1 + se2);
433 double denom = (se1 * se1) / (n1 - 1) + (se2 * se2) / (n2 - 1);
434
435 // Protection against zero denominator (when both variances are zero)
436 if (denom == 0.0) {
437 throw std::invalid_argument("statcpp::ci_mean_diff_welch: cannot compute degrees of freedom with zero variances");
438 }
439
440 double df = num / denom;
441
442 double alpha = 1.0 - confidence;
443 double t_crit = t_quantile(1.0 - alpha / 2.0, df);
444
445 double margin = t_crit * se;
446
447 return {diff - margin, diff + margin, diff, confidence};
448}
449
450// ============================================================================
451// Margin of Error
452// ============================================================================
453
466template <typename Iterator>
467double margin_of_error_mean(Iterator first, Iterator last, double confidence = 0.95)
468{
469 if (confidence <= 0.0 || confidence >= 1.0) {
470 throw std::invalid_argument("statcpp::margin_of_error_mean: confidence must be in (0, 1)");
471 }
472
473 auto n = statcpp::count(first, last);
474 if (n < 2) {
475 throw std::invalid_argument("statcpp::margin_of_error_mean: need at least 2 elements");
476 }
477
478 double se = statcpp::standard_error(first, last);
479 double df = static_cast<double>(n - 1);
480 double alpha = 1.0 - confidence;
481 double t_crit = t_quantile(1.0 - alpha / 2.0, df);
482
483 return t_crit * se;
484}
485
498template <typename Iterator, typename Projection>
499double margin_of_error_mean(Iterator first, Iterator last, double confidence, Projection proj)
500{
501 if (confidence <= 0.0 || confidence >= 1.0) {
502 throw std::invalid_argument("statcpp::margin_of_error_mean: confidence must be in (0, 1)");
503 }
504
505 auto n = statcpp::count(first, last);
506 if (n < 2) {
507 throw std::invalid_argument("statcpp::margin_of_error_mean: need at least 2 elements");
508 }
509
510 double se = statcpp::standard_error(first, last, proj);
511 double df = static_cast<double>(n - 1);
512 double alpha = 1.0 - confidence;
513 double t_crit = t_quantile(1.0 - alpha / 2.0, df);
514
515 return t_crit * se;
516}
517
529inline double margin_of_error_proportion(std::size_t successes, std::size_t n, double confidence = 0.95)
530{
531 if (confidence <= 0.0 || confidence >= 1.0) {
532 throw std::invalid_argument("statcpp::margin_of_error_proportion: confidence must be in (0, 1)");
533 }
534 if (n == 0) {
535 throw std::invalid_argument("statcpp::margin_of_error_proportion: n must be positive");
536 }
537 if (successes > n) {
538 throw std::invalid_argument("statcpp::margin_of_error_proportion: successes cannot exceed n");
539 }
540
541 double p = static_cast<double>(successes) / static_cast<double>(n);
542 double se = std::sqrt(p * (1.0 - p) / static_cast<double>(n));
543
544 double alpha = 1.0 - confidence;
545 double z_crit = normal_quantile(1.0 - alpha / 2.0, 0.0, 1.0);
546
547 return z_crit * se;
548}
549
560inline double margin_of_error_proportion_worst_case(std::size_t n, double confidence = 0.95)
561{
562 if (confidence <= 0.0 || confidence >= 1.0) {
563 throw std::invalid_argument("statcpp::margin_of_error_proportion_worst_case: confidence must be in (0, 1)");
564 }
565 if (n == 0) {
566 throw std::invalid_argument("statcpp::margin_of_error_proportion_worst_case: n must be positive");
567 }
568
569 double alpha = 1.0 - confidence;
570 double z_crit = normal_quantile(1.0 - alpha / 2.0, 0.0, 1.0);
571
572 return z_crit * 0.5 / std::sqrt(static_cast<double>(n));
573}
574
575// ============================================================================
576// Sample Size Calculation (Margin-of-Error based)
577// ============================================================================
578
591inline std::size_t sample_size_for_moe_proportion(double margin_of_error,
592 double confidence_level = 0.95,
593 double p_estimate = 0.5)
594{
595 if (margin_of_error <= 0.0 || margin_of_error >= 1.0) {
596 throw std::invalid_argument("statcpp::sample_size_for_moe_proportion: margin_of_error must be in (0, 1)");
597 }
598 if (confidence_level <= 0.0 || confidence_level >= 1.0) {
599 throw std::invalid_argument("statcpp::sample_size_for_moe_proportion: confidence_level must be in (0, 1)");
600 }
601 if (p_estimate <= 0.0 || p_estimate >= 1.0) {
602 throw std::invalid_argument("statcpp::sample_size_for_moe_proportion: p_estimate must be in (0, 1)");
603 }
604
605 double alpha = 1.0 - confidence_level;
606 double z = normal_quantile(1.0 - alpha / 2.0, 0.0, 1.0);
607
608 // n = (z / MoE)^2 * p(1-p)
609 double n_exact = std::pow(z / margin_of_error, 2.0) * p_estimate * (1.0 - p_estimate);
610
611 // Round up to integer
612 return static_cast<std::size_t>(std::ceil(n_exact));
613}
614
627inline std::size_t sample_size_for_moe_mean(double margin_of_error,
628 double sigma,
629 double confidence_level = 0.95)
630{
631 if (margin_of_error <= 0.0) {
632 throw std::invalid_argument("statcpp::sample_size_for_moe_mean: margin_of_error must be positive");
633 }
634 if (sigma <= 0.0) {
635 throw std::invalid_argument("statcpp::sample_size_for_moe_mean: sigma must be positive");
636 }
637 if (confidence_level <= 0.0 || confidence_level >= 1.0) {
638 throw std::invalid_argument("statcpp::sample_size_for_moe_mean: confidence_level must be in (0, 1)");
639 }
640
641 double alpha = 1.0 - confidence_level;
642 double z = normal_quantile(1.0 - alpha / 2.0, 0.0, 1.0);
643
644 // n = (z * sigma / MoE)^2
645 double n_exact = std::pow(z * sigma / margin_of_error, 2.0);
646
647 // Round up to integer
648 return static_cast<std::size_t>(std::ceil(n_exact));
649}
650
651// ============================================================================
652// Two-Sample Mean Difference Confidence Interval
653// ============================================================================
654
668template <typename Iterator1, typename Iterator2>
669confidence_interval ci_mean_diff_pooled(Iterator1 first1, Iterator1 last1,
670 Iterator2 first2, Iterator2 last2,
671 double confidence = 0.95)
672{
673 // ci_mean_diff と同一のロジック(等分散を仮定した pooled t 検定)
674 return ci_mean_diff(first1, last1, first2, last2, confidence);
675}
676
677// ============================================================================
678// Two-Sample Proportion Difference Confidence Interval
679// ============================================================================
680
692inline confidence_interval ci_proportion_diff(std::size_t successes1, std::size_t n1,
693 std::size_t successes2, std::size_t n2,
694 double confidence = 0.95)
695{
696 if (confidence <= 0.0 || confidence >= 1.0) {
697 throw std::invalid_argument("statcpp::ci_proportion_diff: confidence must be in (0, 1)");
698 }
699 if (n1 == 0 || n2 == 0) {
700 throw std::invalid_argument("statcpp::ci_proportion_diff: sample sizes must be positive");
701 }
702 if (successes1 > n1 || successes2 > n2) {
703 throw std::invalid_argument("statcpp::ci_proportion_diff: successes cannot exceed sample size");
704 }
705
706 double p1 = static_cast<double>(successes1) / static_cast<double>(n1);
707 double p2 = static_cast<double>(successes2) / static_cast<double>(n2);
708
709 double diff = p1 - p2;
710
711 // Standard error for difference of proportions
712 double se1 = p1 * (1.0 - p1) / static_cast<double>(n1);
713 double se2 = p2 * (1.0 - p2) / static_cast<double>(n2);
714 double se = std::sqrt(se1 + se2);
715
716 double alpha = 1.0 - confidence;
717 double z_crit = normal_quantile(1.0 - alpha / 2.0, 0.0, 1.0);
718
719 double margin = z_crit * se;
720
721 return {diff - margin, diff + margin, diff, confidence};
722}
723
724} // namespace statcpp
Basic statistical computation functions.
Continuous distribution functions.
Dispersion and variance calculation functions.
double normal_quantile(double p, double mu=0.0, double sigma=1.0)
Normal distribution quantile function (inverse CDF, percent point function)
confidence_interval ci_mean(Iterator first, Iterator last, double confidence=0.95)
Calculate confidence interval for mean (t-distribution based)
confidence_interval ci_mean_diff(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, double confidence=0.95)
Calculate confidence interval for difference of two-sample means (independent samples,...
double sample_stddev(Iterator first, Iterator last)
Sample standard deviation.
double sample_variance(Iterator first, Iterator last)
Sample variance (unbiased variance)
double margin_of_error_proportion_worst_case(std::size_t n, double confidence=0.95)
Calculate worst-case margin of error for proportion.
confidence_interval ci_mean_diff_pooled(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, double confidence=0.95)
Calculate confidence interval for two-sample mean difference (assuming equal variances)
double var(Iterator first, Iterator last, std::size_t ddof=0)
Variance (ddof = Delta Degrees of Freedom)
std::size_t sample_size_for_moe_proportion(double margin_of_error, double confidence_level=0.95, double p_estimate=0.5)
Calculate sample size for proportion estimation.
double norm_quantile(double p)
Standard normal quantile function.
confidence_interval ci_variance(Iterator first, Iterator last, double confidence=0.95)
Calculate confidence interval for variance (chi-square distribution based)
confidence_interval ci_mean_diff_welch(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, double confidence=0.95)
Calculate confidence interval for difference of two-sample means (Welch method, not assuming equal va...
std::size_t sample_size_for_moe_mean(double margin_of_error, double sigma, double confidence_level=0.95)
Calculate sample size for mean estimation (known population standard deviation)
double chisq_quantile(double p, double df)
Chi-square distribution quantile function.
confidence_interval ci_proportion_wilson(std::size_t successes, std::size_t trials, double confidence=0.95)
Calculate confidence interval for proportion (Wilson method, recommended)
double mean(Iterator first, Iterator last)
Arithmetic mean.
double t_quantile(double p, double df)
t-distribution quantile function (Newton-Raphson method)
double standard_error(Iterator first, Iterator last)
Calculate standard error of the mean.
std::vector< double > diff(Iterator first, Iterator last, std::size_t order=1)
Difference series (first-order or d-th order differencing)
double margin_of_error_mean(Iterator first, Iterator last, double confidence=0.95)
Calculate margin of error for mean.
double margin_of_error_proportion(std::size_t successes, std::size_t n, double confidence=0.95)
Calculate margin of error for proportion.
confidence_interval ci_mean_z(Iterator first, Iterator last, double sigma, double confidence=0.95)
Calculate confidence interval for mean (z-distribution based, known variance)
std::size_t count(Iterator first, Iterator last)
Data count.
confidence_interval ci_proportion_diff(std::size_t successes1, std::size_t n1, std::size_t successes2, std::size_t n2, double confidence=0.95)
Calculate confidence interval for two-sample proportion difference.
confidence_interval ci_proportion(std::size_t successes, std::size_t trials, double confidence=0.95)
Calculate confidence interval for proportion (Wald method)
Structure to store confidence interval results.
double upper
Upper bound of confidence interval.
double lower
Lower bound of confidence interval.
double confidence_level
Confidence level.
double point_estimate
Point estimate.