25 #ifndef LIB_STAT_STATISTIC_H 26 #define LIB_STAT_STATISTIC_H 49 using std::make_tuple;
57 using VecD = std::vector<double>;
62 template<
typename TUP>
64 array_from_tuple (TUP&& tuple)
66 constexpr
auto makeArray = [](
auto&& ... x)
68 return std::array{forward<decltype(x)> (x) ...};
70 return std::apply (makeArray, forward<TUP> (tuple));
73 template<
size_t places>
77 constexpr
double shift{pow(10.0, places)};
78 return std::round(val*shift) / shift;
94 const D*
const b_{
nullptr};
95 const D*
const e_{
nullptr};
99 DataSpan (D
const& begin, D
const& end)
109 :
DataSpan{*std::begin(container), *std::end(container)}
113 using iterator =
const D*;
114 using const_iterator = iterator;
116 size_t size()
const {
return e_ - b_; }
117 bool empty()
const {
return b_ == e_;}
119 iterator begin()
const {
return b_; }
120 iterator end()
const {
return e_; }
121 friend const_iterator begin (
DataSpan const& span){
return span.begin();}
122 friend const_iterator end (
DataSpan const& span){
return span.end(); }
124 D
const& operator[](
size_t i)
const {
return *(b_ + i); }
125 D
const& at(
size_t i)
const 130 return this->operator[](i);
143 template<
typename... NUMS>
145 errorSum (NUMS ...vals)
147 auto sqr = [](
auto val){
return val*val; };
148 return sqrt((sqr(vals)+ ... + 0.0));
157 if (isnil(data))
return 0.0;
159 for (
auto val : data)
161 return sum / data.size();
168 if (isnil(data))
return 0.0;
170 for (
auto val : data)
172 D offset = val - mean;
173 sdev += offset*offset;
175 size_t n = data.size();
181 sdev (VecD
const& data,
double mean)
189 lastN (VecD
const& data,
size_t n)
191 n = min (n, data.size());
192 size_t oldest = data.size() - n;
197 averageLastN (VecD
const& data,
size_t n)
199 return average (lastN (data,n));
203 sdevLastN (VecD
const& data,
size_t n,
double mean)
205 return sdev (lastN (data,n), mean);
218 for (
auto& y : series)
225 return make_tuple (ysum,yysum, xysum);
247 using RegressionData = std::vector<RegressionPoint>;
254 std::array<double,6> sums;
256 auto& [wsum, wxsum, wysum, wxxsum, wyysum, wxysum] = sums;
257 for (
auto& p : points)
262 wxxsum += p.w * p.x*p.x;
263 wyysum += p.w * p.y*p.y;
264 wxysum += p.w * p.x*p.y;
284 auto [wsum, wxsum, wysum, wxxsum, wyysum, wxysum] = computeWeightedStatSums(points);
286 double xm = wxsum / wsum;
287 double ym = wysum / wsum;
288 double varx = wxxsum + xm*xm * wsum - 2*xm * wxsum;
289 double vary = wyysum + ym*ym * wsum - 2*ym * wysum;
290 double cova = wxysum + xm*ym * wsum - ym * wxsum - xm * wysum;
293 double gradient = cova / varx;
294 double socket = ym - gradient * xm;
297 double correlation = wyysum==0.0? 1.0 : gradient * sqrt(varx/vary);
300 size_t n = points.size();
301 VecD predicted; predicted.reserve(n);
302 VecD deltas; deltas.reserve(n);
303 double maxDelta = 0.0;
304 double variance = 0.0;
305 for (
auto& p : points)
307 double y_pred = socket + gradient * p.x;
308 double delta = p.y - y_pred;
309 predicted.push_back (y_pred);
310 deltas.push_back (delta);
311 maxDelta = max (maxDelta, fabs(delta));
312 variance += p.w * delta*delta;
314 variance /= wsum * (n<=2? 1 : (n-2)/
double(n));
316 return make_tuple (socket,gradient
326 computeLinearRegression (RegressionData
const& points)
344 computeTimeSeriesLinearRegression (
DataSpan<D> const& series)
346 if (series.size() < 2)
return make_tuple(0.0,0.0,0.0);
348 auto [ysum,yysum, xysum] = computeStatSums(series);
350 size_t n = series.size();
351 double im = (n-1)/2.0;
352 double ym = ysum / n;
353 double varx = (n-1)*(n+1)/12.0;
354 double vary = yysum/n - ym*ym;
355 double cova = xysum - ysum *(n-1)/2;
358 double gradient = cova / (n*varx);
359 double socket = ym - gradient * im;
362 double correlation = yysum==0.0? 1.0 : gradient * sqrt(varx/vary);
363 return make_tuple (socket,gradient,correlation);
367 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 duplicated by copy-construction, yet may not be moved or transfe...
Lumiera error handling (C++ interface).
Single data point used for linear regression.