QGIS API Documentation  2.14.0-Essen
qgsstatisticalsummary.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsstatisticalsummary.cpp
3  --------------------------------------
4  Date : May 2015
5  Copyright : (C) 2015 by Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsstatisticalsummary.h"
17 #include <limits>
18 #include <qmath.h>
19 #include <QString>
20 #include <QObject>
21 
22 /***************************************************************************
23  * This class is considered CRITICAL and any change MUST be accompanied with
24  * full unit tests in testqgsstatisticalsummary.cpp.
25  * See details in QEP #17
26  ****************************************************************************/
27 
29  : mStatistics( stats )
30 {
31  reset();
32 }
33 
35 {
36 
37 }
38 
40 {
41  mCount = 0;
42  mSum = 0;
43  mMean = 0;
44  mMedian = 0;
47  mStdev = 0;
48  mSampleStdev = 0;
49  mMinority = 0;
50  mMajority = 0;
51  mFirstQuartile = 0;
52  mThirdQuartile = 0;
53  mValueCount.clear();
54 }
55 
56 /***************************************************************************
57  * This class is considered CRITICAL and any change MUST be accompanied with
58  * full unit tests in testqgsstatisticalsummary.cpp.
59  * See details in QEP #17
60  ****************************************************************************/
61 
63 {
64  reset();
65 
66  Q_FOREACH ( double value, values )
67  {
68  mCount++;
69  mSum += value;
70  mMin = qMin( mMin, value );
71  mMax = qMax( mMax, value );
72 
73  if ( mStatistics & QgsStatisticalSummary::Majority || mStatistics & QgsStatisticalSummary::Minority || mStatistics & QgsStatisticalSummary::Variety )
74  mValueCount.insert( value, mValueCount.value( value, 0 ) + 1 );
75  }
76 
77  if ( mCount == 0 )
78  return;
79 
80  mMean = mSum / mCount;
81 
82  if ( mStatistics & QgsStatisticalSummary::StDev || mStatistics & QgsStatisticalSummary::StDevSample )
83  {
84  double sumSquared = 0;
85  Q_FOREACH ( double value, values )
86  {
87  double diff = value - mMean;
88  sumSquared += diff * diff;
89  }
90  mStdev = qPow( sumSquared / values.count(), 0.5 );
91  mSampleStdev = qPow( sumSquared / ( values.count() - 1 ), 0.5 );
92  }
93 
94  QList<double> sorted;
95  if ( mStatistics & QgsStatisticalSummary::Median
99  {
100  sorted = values;
101  qSort( sorted.begin(), sorted.end() );
102  bool even = ( mCount % 2 ) < 1;
103  if ( even )
104  {
105  mMedian = ( sorted[mCount / 2 - 1] + sorted[mCount / 2] ) / 2.0;
106  }
107  else //odd
108  {
109  mMedian = sorted[( mCount + 1 ) / 2 - 1];
110  }
111  }
112 
113  if ( mStatistics & QgsStatisticalSummary::FirstQuartile
114  || mStatistics & QgsStatisticalSummary::InterQuartileRange )
115  {
116  if (( mCount % 2 ) < 1 )
117  {
118  int halfCount = mCount / 2;
119  bool even = ( halfCount % 2 ) < 1;
120  if ( even )
121  {
122  mFirstQuartile = ( sorted[halfCount / 2 - 1] + sorted[halfCount / 2] ) / 2.0;
123  }
124  else //odd
125  {
126  mFirstQuartile = sorted[( halfCount + 1 ) / 2 - 1];
127  }
128  }
129  else
130  {
131  int halfCount = mCount / 2 + 1;
132  bool even = ( halfCount % 2 ) < 1;
133  if ( even )
134  {
135  mFirstQuartile = ( sorted[halfCount / 2 - 1] + sorted[halfCount / 2] ) / 2.0;
136  }
137  else //odd
138  {
139  mFirstQuartile = sorted[( halfCount + 1 ) / 2 - 1];
140  }
141  }
142  }
143 
144  if ( mStatistics & QgsStatisticalSummary::ThirdQuartile
145  || mStatistics & QgsStatisticalSummary::InterQuartileRange )
146  {
147  if (( mCount % 2 ) < 1 )
148  {
149  int halfCount = mCount / 2;
150  bool even = ( halfCount % 2 ) < 1;
151  if ( even )
152  {
153  mThirdQuartile = ( sorted[ halfCount + halfCount / 2 - 1] + sorted[ halfCount + halfCount / 2] ) / 2.0;
154  }
155  else //odd
156  {
157  mThirdQuartile = sorted[( halfCount + 1 ) / 2 - 1 + halfCount ];
158  }
159  }
160  else
161  {
162  int halfCount = mCount / 2 + 1;
163  bool even = ( halfCount % 2 ) < 1;
164  if ( even )
165  {
166  mThirdQuartile = ( sorted[ halfCount + halfCount / 2 - 2 ] + sorted[ halfCount + halfCount / 2 - 1 ] ) / 2.0;
167  }
168  else //odd
169  {
170  mThirdQuartile = sorted[( halfCount + 1 ) / 2 - 2 + halfCount ];
171  }
172  }
173  }
174 
175  if ( mStatistics & QgsStatisticalSummary::Minority || mStatistics & QgsStatisticalSummary::Majority )
176  {
177  QList<int> valueCounts = mValueCount.values();
178  qSort( valueCounts.begin(), valueCounts.end() );
179  if ( mStatistics & QgsStatisticalSummary::Minority )
180  {
181  mMinority = mValueCount.key( valueCounts.first() );
182  }
183  if ( mStatistics & QgsStatisticalSummary::Majority )
184  {
185  mMajority = mValueCount.key( valueCounts.last() );
186  }
187  }
188 
189 }
190 
191 /***************************************************************************
192  * This class is considered CRITICAL and any change MUST be accompanied with
193  * full unit tests in testqgsstatisticalsummary.cpp.
194  * See details in QEP #17
195  ****************************************************************************/
196 
198 {
199  switch ( stat )
200  {
201  case Count:
202  return mCount;
203  case Sum:
204  return mSum;
205  case Mean:
206  return mMean;
207  case Median:
208  return mMedian;
209  case StDev:
210  return mStdev;
211  case StDevSample:
212  return mSampleStdev;
213  case Min:
214  return mMin;
215  case Max:
216  return mMax;
217  case Range:
218  return mMax - mMin;
219  case Minority:
220  return mMinority;
221  case Majority:
222  return mMajority;
223  case Variety:
224  return mValueCount.count();
225  case FirstQuartile:
226  return mFirstQuartile;
227  case ThirdQuartile:
228  return mThirdQuartile;
229  case InterQuartileRange:
230  return mThirdQuartile - mFirstQuartile;
231  case All:
232  return 0;
233  }
234  return 0;
235 }
236 
238 {
239  switch ( statistic )
240  {
241  case Count:
242  return QObject::tr( "Count" );
243  case Sum:
244  return QObject::tr( "Sum" );
245  case Mean:
246  return QObject::tr( "Mean" );
247  case Median:
248  return QObject::tr( "Median" );
249  case StDev:
250  return QObject::tr( "St dev (pop)" );
251  case StDevSample:
252  return QObject::tr( "St dev (sample)" );
253  case Min:
254  return QObject::tr( "Minimum" );
255  case Max:
256  return QObject::tr( "Maximum" );
257  case Range:
258  return QObject::tr( "Range" );
259  case Minority:
260  return QObject::tr( "Minority" );
261  case Majority:
262  return QObject::tr( "Majority" );
263  case Variety:
264  return QObject::tr( "Variety" );
265  case FirstQuartile:
266  return QObject::tr( "Q1" );
267  case ThirdQuartile:
268  return QObject::tr( "Q3" );
269  case InterQuartileRange:
270  return QObject::tr( "IQR" );
271  case All:
272  return QString();
273  }
274  return QString();
275 }
276 
void reset()
Resets the calculated values.
QList< T > values() const
Statistic
Enumeration of flags that specify statistics to be calculated.
Variety (count of distinct) values.
Sample standard deviation of values.
void clear()
QgsStatisticalSummary(const QgsStatisticalSummary::Statistics &stats=All)
Constructor for QgsStatisticalSummary.
QString tr(const char *sourceText, const char *disambiguation, int n)
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
int count(const T &value) const
double statistic(Statistic stat) const
Returns the value of a specified statistic.
static QString displayName(Statistic statistic)
Returns the friendly display name for a statistic.
T & first()
iterator end()
const Key key(const T &value) const
T & last()
void calculate(const QList< double > &values)
Calculates summary statistics for a list of values.
iterator insert(const Key &key, const T &value)
Standard deviation of values.
int count(const Key &key) const
iterator begin()
Range of values (max - min)
const T value(const Key &key) const