numeric
Stats.hpp
Go to the documentation of this file.
1 #ifndef __NUMERIC_STATS_HPP__
2 #define __NUMERIC_STATS_HPP__
3 
4 #include <Eigen/Core>
5 #include <base/Eigen.hpp>
6 
7 namespace numeric
8 {
9 
10 template <class T>
11 struct Square
12 {
13  typedef T Type;
14  static inline Type value( Type a ) { return a * a; }
15  static inline Type value( Type a, Type b ) { return a * b; }
16 };
17 
18 template <class T>
19 struct Zero
20 {
21  static inline T value() { return 0; }
22 };
23 
24 
25 template <class _Scalar, int _Rows, int _Options>
26 struct Square< Eigen::Matrix<_Scalar, _Rows, 1, _Options> >
27 {
28  typedef typename Eigen::Matrix<_Scalar, _Rows, 1, _Options> T;
29  typedef typename Eigen::Matrix<_Scalar, _Rows, _Rows, _Options> Type;
30  static inline Type value( const T& a ) { return a * a.transpose(); }
31  static inline Type value( const T& a, const T& b ) { return a * b.transpose(); }
32 };
33 
34 template <class _Scalar, int _Rows, int _Cols, int _Options>
35 struct Zero< Eigen::Matrix<_Scalar, _Rows, _Cols, _Options> >
36 {
37  typedef Eigen::Matrix<_Scalar, _Rows, _Cols, _Options> T;
38  static inline T value() { return T::Zero(); }
39 };
40 
41 template <class T> T min_el( T a, T b ) { return std::min( a, b ); }
42 template <class T> T max_el( T a, T b ) { return std::max( a, b ); }
43 
44 template <class _Scalar, int _Rows, int _Options>
45 Eigen::Matrix<_Scalar, _Rows, 1, _Options> min_el(
46  Eigen::Matrix<_Scalar, _Rows, 1, _Options> const& a,
47  Eigen::Matrix<_Scalar, _Rows, 1, _Options> const& b )
48 {
49  return a.array().min( b.array() ).matrix();
50 }
51 
52 template <class _Scalar, int _Rows, int _Options>
53 Eigen::Matrix<_Scalar, _Rows, 1, _Options> max_el(
54  Eigen::Matrix<_Scalar, _Rows, 1, _Options> const& a,
55  Eigen::Matrix<_Scalar, _Rows, 1, _Options> const& b )
56 {
57  return a.array().max( b.array() ).matrix();
58 }
59 
65 template <class T>
66 class Stats
67 {
68  typedef typename Square<T>::Type SquareType;
69 
70  T min_;
71  T max_;
72 
73  SquareType M2_;
74  T mean_;
75  double sum_weight_;
76  size_t n_;
77 
78  double ddof_;
79 
80  void init( T const& data);
81 
82 public:
83  Stats();
84  void update( T const& data, double weight = 1.0 );
85  void clear();
86 
87  T min() const;
88  T max() const;
89  T mean() const;
90  SquareType var() const;
91  T stdev() const;
92  double sumWeights() const;
93  size_t n() const;
94 
101  void setDDof(double new_ddof) { ddof_ = new_ddof; }
102 };
103 
104 template <class T>
106 {
107  clear();
108  ddof_ = 0.0;
109 }
110 
111 template <class T>
113  n_ = 0;
114 }
115 
116 template <class T>
117 void Stats<T>::init( T const& data ) {
118 
119  sum_weight_ = 0.0;
120  min_ = data;
121  max_ = data;
122  M2_ = Zero<SquareType>::value();
123  mean_ = Zero<T>::value();
124 }
125 
126 template <>
127 inline void Stats<base::VectorXd>::init( base::VectorXd const& data ) {
128 
129  int rows = data.rows();
130 
131  sum_weight_ = 0.0;
132  min_ = data;
133  max_ = data;
134  M2_ = base::MatrixXd::Zero(rows,rows);
135  mean_ = base::VectorXd::Zero(rows);
136 }
137 
138 template <class T>
139 void Stats<T>::update( T const& data, double weight )
140 {
141  if( !n_ )
142  {
143  init(data);
144  }
145  else
146  {
147  min_ = numeric::min_el(min_, data);
148  max_ = numeric::max_el(max_, data);
149  }
150 
151  //
152  // algorithm is based on
153  // D. H. D. West (1979). Communications of the ACM, 22, 9, 532-535:
154  // Updating Mean and Variance Estimates: An Improved Method
155  //
156  // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
157  //
158  double temp = weight + sum_weight_;
159  T delta = data - mean_;
160  T R = delta * weight / temp;
161  mean_ = mean_ + R;
162  M2_ = M2_ + sum_weight_ * Square<T>::value( delta, R );
163  sum_weight_ = temp;
164 
165  n_++;
166 }
167 
168 template <class T>
169 double Stats<T>::sumWeights() const
170 {
171  return sum_weight_;
172 }
173 
174 template <class T>
175 T Stats<T>::mean() const
176 {
177  return mean_;
178 }
179 
180 template <class T>
181 inline typename Stats<T>::SquareType Stats<T>::var() const
182 {
183  return (sum_weight_ > 0.0 ) ? SquareType(M2_ / (sum_weight_ - ddof_)) : Zero<SquareType>::value();
184 }
185 
186 template <>
187 inline Stats<base::VectorXd>::SquareType Stats<base::VectorXd>::var() const
188 {
189  return ( sum_weight_ > 0.0 ) ? SquareType(M2_ / (sum_weight_ - ddof_)) :
190  base::MatrixXd::Zero(M2_.rows(),M2_.cols());
191 }
192 
193 template <class T>
195 {
196  return sqrt( var() );
197 }
198 
199 template <>
200 inline base::VectorXd Stats<base::VectorXd>::stdev() const
201 {
202  return var().diagonal().array().sqrt();
203 }
204 
205 template <class T>
206 T Stats<T>::min() const
207 {
208  return min_;
209 }
210 
211 template <class T>
212 T Stats<T>::max() const
213 {
214  return max_;
215 }
216 
217 template <class T>
218 size_t Stats<T>::n() const
219 {
220  return n_;
221 }
222 
234 class SeriesStats {
235 
236  Eigen::VectorXd min_;
237  Eigen::VectorXd max_;
238  Eigen::VectorXd mean_;
239  Eigen::VectorXd stdev_;
240 
241  Eigen::MatrixXd var_;
242 
243  size_t n_;
244 
245 protected:
246 
247  template<typename Derived>
248  Eigen::VectorXd weightOnes(const Eigen::MatrixBase<Derived>& data) {
249  return Eigen::VectorXd::Ones(data.cols());
250  }
251 
252  template <typename Derived>
253  void compute (const Eigen::MatrixBase<Derived>& data) {
254  compute(data, weightOnes(data), 0.0);
255  }
256 
257  template <typename Derived>
258  void compute (const Eigen::MatrixBase<Derived>& data, double ddof) {
259  compute(data, weightOnes(data), ddof);
260  }
261 
262  template <typename Derived1, typename Derived2>
263  void compute (const Eigen::MatrixBase<Derived1>& data,
264  const Eigen::MatrixBase<Derived2>& weights) {
265 
266  compute(data, weights, 0.0);
267  }
268 
269  template <typename Derived1, typename Derived2>
270  void compute (const Eigen::MatrixBase<Derived1>& data,
271  const Eigen::MatrixBase<Derived2>& weights, double ddof) {
272 
273  min_ = data.array().rowwise().minCoeff();
274  max_ = data.array().rowwise().maxCoeff();
275  n_ = data.cols();
276  double w_sum = weights.sum();
277  Eigen::MatrixXd weighted_data = data * (weights / w_sum * n_).asDiagonal();
278  mean_ = weighted_data.rowwise().mean();
279  Eigen::MatrixXd centered_data = weighted_data.colwise() - mean_;
280  var_ = centered_data * centered_data.adjoint() / ( n_ - ddof );
281  stdev_ = var_.diagonal().array().sqrt();
282  }
283 
284 public:
285 
286  template <typename Derived>
287  SeriesStats(const Eigen::MatrixBase<Derived>& data) { compute(data); }
288 
289  template <typename Derived>
290  SeriesStats(const Eigen::MatrixBase<Derived>& data, double ddof) {
291  compute(data, ddof);
292  }
293 
294  template <typename Derived1, typename Derived2>
295  SeriesStats(const Eigen::MatrixBase<Derived1>& data,
296  const Eigen::MatrixBase<Derived2>& weights) {
297  compute(data, weights);
298  }
299 
308  template <typename Derived1, typename Derived2>
309  SeriesStats(const Eigen::MatrixBase<Derived1>& data,
310  const Eigen::MatrixBase<Derived2>& weights, double ddof) {
311  compute(data, weights, ddof);
312  }
313 
314  const Eigen::VectorXd& min() const { return min_; }
315  const Eigen::VectorXd& max() const { return max_; }
316  const Eigen::VectorXd& mean() const { return mean_; }
317  const Eigen::MatrixXd& var() const { return var_; }
318  const Eigen::VectorXd& stdev() const { return stdev_; }
319  size_t n() const { return n_; }
320 
321 };
322 
323 } // namespace numeric
324 
325 #endif
void compute(const Eigen::MatrixBase< Derived > &data, double ddof)
Definition: Stats.hpp:258
double sumWeights() const
Definition: Stats.hpp:169
const Eigen::VectorXd & stdev() const
Definition: Stats.hpp:318
const Eigen::MatrixXd & var() const
Definition: Stats.hpp:317
static T value()
Definition: Stats.hpp:21
static Type value(const T &a, const T &b)
Definition: Stats.hpp:31
static Type value(Type a, Type b)
Definition: Stats.hpp:15
SeriesStats(const Eigen::MatrixBase< Derived1 > &data, const Eigen::MatrixBase< Derived2 > &weights, double ddof)
Definition: Stats.hpp:309
Definition: Circle.hpp:6
const Eigen::VectorXd & max() const
Definition: Stats.hpp:315
Definition: Stats.hpp:66
SeriesStats(const Eigen::MatrixBase< Derived > &data, double ddof)
Definition: Stats.hpp:290
void compute(const Eigen::MatrixBase< Derived > &data)
Definition: Stats.hpp:253
size_t n() const
Definition: Stats.hpp:319
void setDDof(double new_ddof)
Definition: Stats.hpp:101
SeriesStats(const Eigen::MatrixBase< Derived > &data)
Definition: Stats.hpp:287
SeriesStats(const Eigen::MatrixBase< Derived1 > &data, const Eigen::MatrixBase< Derived2 > &weights)
Definition: Stats.hpp:295
const Eigen::VectorXd & mean() const
Definition: Stats.hpp:316
T min_el(T a, T b)
Definition: Stats.hpp:41
size_t n() const
Definition: Stats.hpp:218
SquareType var() const
Definition: Stats.hpp:181
Eigen::VectorXd weightOnes(const Eigen::MatrixBase< Derived > &data)
Definition: Stats.hpp:248
Eigen::Matrix< _Scalar, _Rows, _Cols, _Options > T
Definition: Stats.hpp:37
Eigen::Matrix< _Scalar, _Rows, 1, _Options > T
Definition: Stats.hpp:28
Definition: Stats.hpp:234
Stats()
Definition: Stats.hpp:105
static Type value(Type a)
Definition: Stats.hpp:14
T min() const
Definition: Stats.hpp:206
T Type
Definition: Stats.hpp:13
void clear()
Definition: Stats.hpp:112
T mean() const
Definition: Stats.hpp:175
T max_el(T a, T b)
Definition: Stats.hpp:42
T stdev() const
Definition: Stats.hpp:194
T max() const
Definition: Stats.hpp:212
Definition: Stats.hpp:11
Definition: Stats.hpp:19
const Eigen::VectorXd & min() const
Definition: Stats.hpp:314
Eigen::Matrix< _Scalar, _Rows, _Rows, _Options > Type
Definition: Stats.hpp:29
void compute(const Eigen::MatrixBase< Derived1 > &data, const Eigen::MatrixBase< Derived2 > &weights, double ddof)
Definition: Stats.hpp:270
void compute(const Eigen::MatrixBase< Derived1 > &data, const Eigen::MatrixBase< Derived2 > &weights)
Definition: Stats.hpp:263
static Type value(const T &a)
Definition: Stats.hpp:30
void update(T const &data, double weight=1.0)
Definition: Stats.hpp:139