Skip to content

Commit

Permalink
New class QgsDateTimeStatisticalSummary
Browse files Browse the repository at this point in the history
Calculates summary statistics on lists of datetime values, such
as count, count distinct, min, max and range
  • Loading branch information
nyalldawson committed May 11, 2016
1 parent 0d165e5 commit b053ad8
Show file tree
Hide file tree
Showing 7 changed files with 528 additions and 0 deletions.
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -39,6 +39,7 @@
%Include qgsdataitemproviderregistry.sip
%Include qgsdataprovider.sip
%Include qgsdatasourceuri.sip
%Include qgsdatetimestatisticalsummary.sip
%Include qgsdatumtransformstore.sip
%Include qgsdbfilterproxymodel.sip
%Include qgsdistancearea.sip
Expand Down
104 changes: 104 additions & 0 deletions python/core/qgsdatetimestatisticalsummary.sip
@@ -0,0 +1,104 @@
/** \ingroup core
* \class QgsDateTimeStatisticalSummary
* \brief Calculator for summary statistics and aggregates for a list of datetimes.
*
* Statistics are calculated by calling @link calculate @endlink and passing a list of datetimes. 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.16
*/

class QgsDateTimeStatisticalSummary
{
%TypeHeaderCode
#include <qgsdatetimestatisticalsummary.h>
%End

public:

//! Enumeration of flags that specify statistics to be calculated
enum Statistic
{
Count, //!< Count
CountDistinct, //!< Number of distinct datetime values
CountMissing, //!< Number of missing (null) values
Min, //!< Minimum (earliest) datetime value
Max, //!< Maximum (latest) datetime value
Range, //!< Interval between earliest and latest datetime value
All, //! All statistics
};
typedef QFlags<QgsDateTimeStatisticalSummary::Statistic> Statistics;

/** Constructor for QgsDateTimeStatisticalSummary
* @param stats flags for statistics to calculate
*/
QgsDateTimeStatisticalSummary( const QgsDateTimeStatisticalSummary::Statistics& stats = All );

/** Returns flags which specify which statistics will be calculated. Some statistics
* are always calculated (eg count).
* @see setStatistics
*/
Statistics statistics() const;

/** Sets flags which specify which statistics will be calculated. Some statistics
* are always calculated (eg count).
* @param stats flags for statistics to calculate
* @see statistics
*/
void setStatistics( const Statistics& stats );

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

/** Calculates summary statistics for a list of variants. Any non-string variants will be
* ignored.
* @param values list of variants
*/
void calculate( const QVariantList& values );

/** Returns the value of a specified statistic
* @param stat statistic to return
* @returns calculated value of statistic
*/
QVariant statistic( Statistic stat ) const;

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

/** Returns the number of distinct datetime values.
*/
int countDistinct() const;

/** Returns the set of distinct datetime values.
*/
QSet< QDateTime > distinctValues() const;

/** Returns the number of missing (null) datetime values.
*/
int countMissing() const;

/** Returns the minimum (earliest) non-null datetime value.
*/
QDateTime min() const;

/** Returns the maximum (latest) non-null datetime value.
*/
QDateTime max() const;

/** Returns the range (interval between earliest and latest non-null datetime values).
*/
QgsInterval range() const;

/** Returns the friendly display name for a statistic
* @param statistic statistic to return name for
*/
static QString displayName( Statistic statistic );

};

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

2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -100,6 +100,7 @@ SET(QGIS_CORE_SRCS
qgsdataitemprovider.cpp
qgsdataitemproviderregistry.cpp
qgsdatasourceuri.cpp
qgsdatetimestatisticalsummary.cpp
qgsdatumtransformstore.cpp
qgsdbfilterproxymodel.cpp
qgsdiagramrendererv2.cpp
Expand Down Expand Up @@ -617,6 +618,7 @@ SET(QGIS_CORE_HDRS
qgsdataitemprovider.h
qgsdataitemproviderregistry.h
qgsdatasourceuri.h
qgsdatetimestatisticalsummary.h
qgsdatumtransformstore.h
qgsdbfilterproxymodel.h
qgsdiagramrendererv2.h
Expand Down
144 changes: 144 additions & 0 deletions src/core/qgsdatetimestatisticalsummary.cpp
@@ -0,0 +1,144 @@
/***************************************************************************
qgsdatetimestatisticalsummary.cpp
---------------------------------
Date : May 2016
Copyright : (C) 2016 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 "qgsdatetimestatisticalsummary.h"
#include <QString>
#include <QDateTime>
#include <QStringList>
#include <QObject>
#include <QVariant>
#include <QVariantList>
#include "limits.h"

/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests in test_qgsdatetimestatisticalsummary.py.
* See details in QEP #17
****************************************************************************/

QgsDateTimeStatisticalSummary::QgsDateTimeStatisticalSummary( const QgsDateTimeStatisticalSummary::Statistics& stats )
: mStatistics( stats )
{
reset();
}

void QgsDateTimeStatisticalSummary::reset()
{
mCount = 0;
mValues.clear();
mCountMissing = 0;
mMin = QDateTime();
mMax = QDateTime();
}

void QgsDateTimeStatisticalSummary::calculate( const QVariantList& values )
{
reset();

Q_FOREACH ( const QVariant& variant, values )
{
if ( variant.type() == QVariant::DateTime )
{
testDateTime( variant.toDateTime() );
}
else if ( variant.type() == QVariant::Date )
{
QDate date = variant.toDate();
testDateTime( date.isValid() ? QDateTime( date, QTime( 0, 0, 0 ) )
: QDateTime() );
}
// QTime?
}
}

void QgsDateTimeStatisticalSummary::testDateTime( const QDateTime& dateTime )
{
mCount++;

if ( !dateTime.isValid() )
mCountMissing++;

if ( mStatistics & CountDistinct )
{
mValues << dateTime;
}
if ( mStatistics & Min || mStatistics & Range )
{
if ( mMin.isValid() && dateTime.isValid() )
{
mMin = qMin( mMin, dateTime );
}
else if ( !mMin.isValid() && dateTime.isValid() )
{
mMin = dateTime;
}
}
if ( mStatistics & Max || mStatistics & Range )
{
if ( mMax.isValid() && dateTime.isValid() )
{
mMax = qMax( mMax, dateTime );
}
else if ( !mMax.isValid() && dateTime.isValid() )
{
mMax = dateTime;
}
}
}

QVariant QgsDateTimeStatisticalSummary::statistic( QgsDateTimeStatisticalSummary::Statistic stat ) const
{
switch ( stat )
{
case Count:
return mCount;
case CountDistinct:
return mValues.count();
case CountMissing:
return mCountMissing;
case Min:
return mMin;
case Max:
return mMax;
case Range:
return QVariant::fromValue( mMax - mMin );
case All:
return 0;
}
return 0;
}

QString QgsDateTimeStatisticalSummary::displayName( QgsDateTimeStatisticalSummary::Statistic statistic )
{
switch ( statistic )
{
case Count:
return QObject::tr( "Count" );
case CountDistinct:
return QObject::tr( "Count (distinct)" );
case CountMissing:
return QObject::tr( "Count (missing)" );
case Min:
return QObject::tr( "Minimum (earliest)" );
case Max:
return QObject::tr( "Maximum (latest)" );
case Range:
return QObject::tr( "Range (interval)" );
case All:
return QString();
}
return QString();
}

0 comments on commit b053ad8

Please sign in to comment.