34 #ifndef LIB_STAT_STATISTIC_H 35 #define LIB_STAT_STATISTIC_H 58 using std::make_tuple;
66 using VecD = std::vector<double>;
71 template<
typename TUP>
73 array_from_tuple (TUP&& tuple)
75 constexpr
auto makeArray = [](
auto&& ... x)
77 return std::array{forward<decltype(x)> (x) ...};
79 return std::apply (makeArray, forward<TUP> (tuple));
82 template<
size_t places>
86 constexpr
double shift{pow(10.0, places)};
87 return std::round(val*shift) / shift;
103 const D*
const b_{
nullptr};
104 const D*
const e_{
nullptr};
108 DataSpan (D
const& begin, D
const& end)
118 :
DataSpan{*std::begin(container), *std::end(container)}
122 using iterator =
const D*;
123 using const_iterator = iterator;
125 size_t size()
const {
return e_ - b_; }
126 bool empty()
const {
return b_ == e_;}
128 iterator begin()
const {
return b_; }
129 iterator end()
const {
return e_; }
130 friend const_iterator begin (
DataSpan const& span){
return span.begin();}
131 friend const_iterator end (
DataSpan const& span){
return span.end(); }
133 D
const& operator[](
size_t i)
const {
return *(b_ + i); }
134 D
const& at(
size_t i)
const 139 return this->operator[](i);
152 template<
typename... NUMS>
154 errorSum (NUMS ...vals)
156 auto sqr = [](
auto val){
return val*val; };
157 return sqrt((sqr(vals)+ ... + 0.0));
166 if (isnil(data))
return 0.0;
168 for (
auto val : data)
170 return sum / data.size();
177 if (isnil(data))
return 0.0;
179 for (
auto val : data)
181 D offset = val - mean;
182 sdev += offset*offset;
184 size_t n = data.size();
190 sdev (VecD
const& data,
double mean)
198 lastN (VecD
const& data,
size_t n)
200 n = min (n, data.size());
201 size_t oldest = data.size() - n;
206 averageLastN (VecD
const& data,
size_t n)
208 return average (lastN (data,n));
212 sdevLastN (VecD
const& data,
size_t n,
double mean)
214 return sdev (lastN (data,n), mean);
227 for (
auto& y : series)
234 return make_tuple (ysum,yysum, xysum);
256 using RegressionData = std::vector<RegressionPoint>;
263 std::array<double,6> sums;
265 auto& [wsum, wxsum, wysum, wxxsum, wyysum, wxysum] = sums;
266 for (
auto& p : points)
271 wxxsum += p.w * p.x*p.x;
272 wyysum += p.w * p.y*p.y;
273 wxysum += p.w * p.x*p.y;
293 auto [wsum, wxsum, wysum, wxxsum, wyysum, wxysum] = computeWeightedStatSums(points);
295 double xm = wxsum / wsum;
296 double ym = wysum / wsum;
297 double varx = wxxsum + xm*xm * wsum - 2*xm * wxsum;
298 double vary = wyysum + ym*ym * wsum - 2*ym * wysum;
299 double cova = wxysum + xm*ym * wsum - ym * wxsum - xm * wysum;
302 double gradient = cova / varx;
303 double socket = ym - gradient * xm;
306 double correlation = wyysum==0.0? 1.0 : gradient * sqrt(varx/vary);
309 size_t n = points.size();
310 VecD predicted; predicted.reserve(n);
311 VecD deltas; deltas.reserve(n);
312 double maxDelta = 0.0;
313 double variance = 0.0;
314 for (
auto& p : points)
316 double y_pred = socket + gradient * p.x;
317 double delta = p.y - y_pred;
318 predicted.push_back (y_pred);
319 deltas.push_back (delta);
320 maxDelta = max (maxDelta, fabs(delta));
321 variance += p.w * delta*delta;
323 variance /= wsum * (n<=2? 1 : (n-2)/
double(n));
325 return make_tuple (socket,gradient
335 computeLinearRegression (RegressionData
const& points)
353 computeTimeSeriesLinearRegression (
DataSpan<D> const& series)
355 if (series.size() < 2)
return make_tuple(0.0,0.0,0.0);
357 auto [ysum,yysum, xysum] = computeStatSums(series);
359 size_t n = series.size();
360 double im = (n-1)/2.0;
361 double ym = ysum / n;
362 double varx = (n-1)*(n+1)/12.0;
363 double vary = yysum/n - ym*ym;
364 double cova = xysum - ysum *(n-1)/2;
367 double gradient = cova / (n*varx);
368 double socket = ym - gradient * im;
371 double correlation = yysum==0.0? 1.0 : gradient * sqrt(varx/vary);
372 return make_tuple (socket,gradient,correlation);
376 computeTimeSeriesLinearRegression (VecD
const& series)
Helper template(s) for creating Lumiera Forward Iterators.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Read-only view into a segment within a sequence of data.
Derived specific exceptions within Lumiera's exception hierarchy.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Types marked with this mix-in may be created by copy-construction (or move construction), but may be not reassigned thereafter.
Lumiera error handling (C++ interface).
Single data point used for linear regression.