Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add QgsStatisticalSummary class for calculating stats from a list
of values.
  • Loading branch information
nyalldawson committed May 2, 2015
1 parent bb0e583 commit 154468b
Show file tree
Hide file tree
Showing 7 changed files with 504 additions and 0 deletions.
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -103,6 +103,7 @@
%Include qgssnapper.sip
%Include qgssnappingutils.sip
%Include qgsspatialindex.sip
%Include qgsstatisticalsummary.sip
%Include qgstolerance.sip
%Include qgsvectordataprovider.sip
%Include qgsvectorfilewriter.sip
Expand Down
135 changes: 135 additions & 0 deletions python/core/qgsstatisticalsummary.sip
@@ -0,0 +1,135 @@
/** \ingroup core
* \class QgsStatisticalSummary
* \brief Calculator for summary statistics for a list of doubles.
*
* Statistics are calculated by calling @link calculate @endlink and passing a list of doubles. The
* individual statistics can then be retrieved using the associated methods. Note that not all statistics
* are calculated by default. Statistics which require slower computations are only calculated by
* specifying the statistic in the constructor or via @link setStatistics @endlink.
*
* \note Added in version 2.9
*/

class QgsStatisticalSummary
{
%TypeHeaderCode
#include <qgsstatisticalsummary.h>
%End

public:

//! Enumeration of flags that specify statistics to be calculated
enum Statistic
{
Count , //!< Count
Sum, //!< Sum of values
Mean, //!< Mean of values
Median, //!< Median of values
StDev, //!< Standard deviation of values
StDevSample, //!< Sample standard deviation of values
Min, //!< Min of values
Max, //!< Max of values
Range, //!< Range of values (max - min)
Minority, //!< Minority of values
Majority, //!< Majority of values
Variety, //!< Variety (count of distinct) values
All
};

typedef QFlags<QgsStatisticalSummary::Statistic> Statistics;

/** Constructor for QgsStatisticalSummary
* @param stats flags for statistics to calculate
*/
QgsStatisticalSummary( QgsStatisticalSummary::Statistics stats = QgsStatisticalSummary::Statistics( 0 ) );

virtual ~QgsStatisticalSummary();

/** Returns flags which specify which statistics will be calculated. Some statistics
* are always calculated (eg sum, min and max).
* @see setStatistics
*/
QgsStatisticalSummary::Statistics statistics() const;

/** Sets flags which specify which statistics will be calculated. Some statistics
* are always calculated (eg sum, min and max).
* @param stats flags for statistics to calculate
* @see statistics
*/
void setStatistics( QgsStatisticalSummary::Statistics stats );

/** Resets the calculated values
*/
void reset();

/** Calculates summary statistics for a list of values
* @param values list of doubles
*/
void calculate( const QList<double>& values );

/** Returns calculated count of values
*/
int count() const;

/** Returns calculated sum of values
*/
double sum() const;

/** Returns calculated mean of values
*/
double mean() const;

/** Returns calculated median of values. This is only calculated if Statistic::Median has
* been specified in the constructor or via setStatistics.
*/
double median() const;

/** Returns calculated minimum from values.
*/
double min() const;

/** Returns calculated maximum from values.
*/
double max() const;

/** Returns calculated range (difference between maximum and minimum values).
*/
double range() const;

/** Returns population standard deviation. This is only calculated if Statistic::StDev has
* been specified in the constructor or via setStatistics.
* @see sampleStDev
*/
double stDev() const;

/** Returns sample standard deviation. This is only calculated if Statistic::StDev has
* been specified in the constructor or via setStatistics.
* @see stDev
*/
double sampleStDev() const;

/** Returns variety of values. The variety is the count of unique values from the list.
* This is only calculated if Statistic::Variety has been specified in the constructor
* or via setStatistics.
*/
int variety() const;

/** Returns minority of values. The minority is the value with least occurances in the list
* This is only calculated if Statistic::Minority has been specified in the constructor
* or via setStatistics.
* @see majority
*/
double minority() const;

/** Returns majority of values. The majority is the value with most occurances in the list
* This is only calculated if Statistic::Majority has been specified in the constructor
* or via setStatistics.
* @see minority
*/
double majority() const;

};

QFlags<QgsStatisticalSummary::Statistic> operator|(QgsStatisticalSummary::Statistic f1, QFlags<QgsStatisticalSummary::Statistic> f2);


2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -168,6 +168,7 @@ SET(QGIS_CORE_SRCS
qgssnapper.cpp
qgssnappingutils.cpp
qgsspatialindex.cpp
qgsstatisticalsummary.cpp
qgstransaction.cpp
qgstolerance.cpp
qgsvectordataprovider.cpp
Expand Down Expand Up @@ -554,6 +555,7 @@ SET(QGIS_CORE_HDRS
qgssnapper.h
qgssnappingutils.h
qgsspatialindex.h
qgsstatisticalsummary.h
qgstolerance.h
qgstransaction.h
qgsvectordataprovider.h
Expand Down
109 changes: 109 additions & 0 deletions src/core/qgsstatisticalsummary.cpp
@@ -0,0 +1,109 @@
/***************************************************************************
qgsstatisticalsummary.cpp
--------------------------------------
Date : May 2015
Copyright : (C) 2015 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsstatisticalsummary.h"
#include <limits>
#include <qmath.h>


QgsStatisticalSummary::QgsStatisticalSummary( Statistics stats )
: mStatistics( stats )
{
reset();
}

QgsStatisticalSummary::~QgsStatisticalSummary()
{

}

void QgsStatisticalSummary::reset()
{
mCount = 0;
mSum = 0;
mMean = 0;
mMedian = 0;
mMin = std::numeric_limits<double>::max();
mMax = std::numeric_limits<double>::min();
mStdev = 0;
mSampleStdev = 0;
mMinority = 0;
mMajority = 0;
mValueCount.clear();
}

void QgsStatisticalSummary::calculate( const QList<double> &values )
{
reset();

foreach ( double value, values )
{
mCount++;
mSum += value;
mMin = qMin( mMin, value );
mMax = qMax( mMax, value );

if ( mStatistics & QgsStatisticalSummary::Majority || mStatistics & QgsStatisticalSummary::Minority || mStatistics & QgsStatisticalSummary::Variety )
mValueCount.insert( value, mValueCount.value( value, 0 ) + 1 );
}

if ( mCount == 0 )
return;

mMean = mSum / mCount;

if ( mStatistics & QgsStatisticalSummary::StDev )
{
double sumSquared = 0;
foreach ( double value, values )
{
double diff = value - mMean;
sumSquared += diff * diff;
}
mStdev = qPow( sumSquared / values.count(), 0.5 );
mSampleStdev = qPow( sumSquared / ( values.count() - 1 ), 0.5 );
}

if ( mStatistics & QgsStatisticalSummary::Median )
{
QList<double> sorted = values;
qSort( sorted.begin(), sorted.end() );
bool even = ( mCount % 2 ) < 1;
if ( even )
{
mMedian = ( sorted[mCount / 2 - 1] + sorted[mCount / 2] ) / 2.0;
}
else //odd
{
mMedian = sorted[( mCount + 1 ) / 2 - 1];
}
}

if ( mStatistics & QgsStatisticalSummary::Minority || mStatistics & QgsStatisticalSummary::Majority )
{
QList<int> valueCounts = mValueCount.values();
qSort( valueCounts.begin(), valueCounts.end() );
if ( mStatistics & QgsStatisticalSummary::Minority )
{
mMinority = mValueCount.key( valueCounts.first() );
}
if ( mStatistics & QgsStatisticalSummary::Majority )
{
mMajority = mValueCount.key( valueCounts.last() );
}
}

}

0 comments on commit 154468b

Please sign in to comment.