def testStringToAggregate(self): """ test converting strings to aggregate types """ tests = [[QgsAggregateCalculator.Count, ' cOUnT '], [QgsAggregateCalculator.CountDistinct, ' count_distinct '], [QgsAggregateCalculator.CountMissing, 'COUNT_MISSING'], [QgsAggregateCalculator.Min, ' MiN'], [QgsAggregateCalculator.Max, 'mAX'], [QgsAggregateCalculator.Sum, 'sum'], [QgsAggregateCalculator.Mean, 'MEAn '], [QgsAggregateCalculator.Median, 'median'], [QgsAggregateCalculator.StDev, 'stdev'], [QgsAggregateCalculator.StDevSample, 'stdevsample'], [QgsAggregateCalculator.Range, 'range'], [QgsAggregateCalculator.Minority, 'minority'], [QgsAggregateCalculator.Majority, 'majority'], [QgsAggregateCalculator.FirstQuartile, 'q1'], [QgsAggregateCalculator.ThirdQuartile, 'q3'], [QgsAggregateCalculator.InterQuartileRange, 'iqr'], [QgsAggregateCalculator.StringMinimumLength, 'min_length'], [QgsAggregateCalculator.StringMaximumLength, 'max_length'], [QgsAggregateCalculator.StringConcatenate, 'concatenate'], [QgsAggregateCalculator.GeometryCollect, 'collect']] for t in tests: agg, ok = QgsAggregateCalculator.stringToAggregate(t[1]) self.assertTrue(ok) self.assertEqual(agg, t[0]) # test some bad values agg, ok = QgsAggregateCalculator.stringToAggregate('') self.assertFalse(ok) agg, ok = QgsAggregateCalculator.stringToAggregate('bad') self.assertFalse(ok)
def testGeometry(self): """ Test calculation of aggregates on geometry expressions """ layer = QgsVectorLayer("Point?", "layer", "memory") pr = layer.dataProvider() # must be same length: geometry_values = [ QgsGeometry.fromWkt("Point ( 0 0 )"), QgsGeometry.fromWkt("Point ( 1 1 )"), QgsGeometry.fromWkt("Point ( 2 2 )"), ] features = [] for i in range(len(geometry_values)): f = QgsFeature() f.setGeometry(geometry_values[i]) features.append(f) self.assertTrue(pr.addFeatures(features)) agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.GeometryCollect, "$geometry") self.assertTrue(ok) expwkt = "MultiPoint ((0 0), (1 1), (2 2))" wkt = val.exportToWkt() self.assertTrue(compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt))
def testParameters(self): """ Test setting parameters""" a = QgsAggregateCalculator(None) params = QgsAggregateCalculator.AggregateParameters() params.filter = 'string filter' params.delimiter = 'delim' a.setParameters(params) self.assertEqual(a.filter(), 'string filter') self.assertEqual(a.delimiter(), 'delim')
def testParameters(self): """ Test setting parameters""" a = QgsAggregateCalculator(None) params = QgsAggregateCalculator.AggregateParameters() params.filter = "string filter" params.delimiter = "delim" a.setParameters(params) self.assertEqual(a.filter(), "string filter") self.assertEqual(a.delimiter(), "delim")
def testLayer(self): """ Test setting/retrieving layer """ a = QgsAggregateCalculator(None) self.assertEqual(a.layer(), None) # should not crash val, ok = a.calculate(QgsAggregateCalculator.Sum, "field") self.assertFalse(ok) layer = QgsVectorLayer("Point?field=fldint:integer&field=flddbl:double", "layer", "memory") a = QgsAggregateCalculator(layer) self.assertEqual(a.layer(), layer)
def testFilter(self): """ test calculating aggregate with filter """ layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) agg = QgsAggregateCalculator(layer) filter_string = "fldint > 2" agg.setFilter(filter_string) self.assertEqual(agg.filter(), filter_string) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 20) # remove filter and retest agg.setFilter(None) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 24)
def testExpressionNoMatch(self): """ test aggregate calculation using an expression with no features """ # no features layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") # sum agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, None) # count agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Count, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 0) # count distinct agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.CountDistinct, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 0) # count missing agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.CountMissing, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 0)
def testString(self): """ Test calculation of aggregates on string fields""" layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory") pr = layer.dataProvider() values = ['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd'] features = [] for v in values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'fldstring', 9], [QgsAggregateCalculator.CountDistinct, 'fldstring', 6], [QgsAggregateCalculator.CountMissing, 'fldstring', 2], [QgsAggregateCalculator.Min, 'fldstring', 'aaaa'], [QgsAggregateCalculator.Max, 'fldstring', 'eeee'], [QgsAggregateCalculator.StringMinimumLength, 'fldstring', 0], [QgsAggregateCalculator.StringMaximumLength, 'fldstring', 8], [QgsAggregateCalculator.ArrayAggregate, 'fldstring', values], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # test string concatenation agg.setDelimiter(',') self.assertEqual(agg.delimiter(), ',') val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenate, 'fldstring') self.assertTrue(ok) self.assertEqual(val, 'cc,aaaa,bbbbbbbb,aaaa,eeee,,eeee,,dddd') val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenateUnique, 'fldstring') self.assertTrue(ok) self.assertEqual(val, 'cc,aaaa,bbbbbbbb,eeee,,dddd') # bad tests - the following stats should not be calculatable for string fields for t in [QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Range, QgsAggregateCalculator.Minority, QgsAggregateCalculator.Majority, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange ]: val, ok = agg.calculate(t, 'fldstring') self.assertFalse(ok)
def testStringToAggregate(self): """ test converting strings to aggregate types """ tests = [ [QgsAggregateCalculator.Count, " cOUnT "], [QgsAggregateCalculator.CountDistinct, " count_distinct "], [QgsAggregateCalculator.CountMissing, "COUNT_MISSING"], [QgsAggregateCalculator.Min, " MiN"], [QgsAggregateCalculator.Max, "mAX"], [QgsAggregateCalculator.Sum, "sum"], [QgsAggregateCalculator.Mean, "MEAn "], [QgsAggregateCalculator.Median, "median"], [QgsAggregateCalculator.StDev, "stdev"], [QgsAggregateCalculator.StDevSample, "stdevsample"], [QgsAggregateCalculator.Range, "range"], [QgsAggregateCalculator.Minority, "minority"], [QgsAggregateCalculator.Majority, "majority"], [QgsAggregateCalculator.FirstQuartile, "q1"], [QgsAggregateCalculator.ThirdQuartile, "q3"], [QgsAggregateCalculator.InterQuartileRange, "iqr"], [QgsAggregateCalculator.StringMinimumLength, "min_length"], [QgsAggregateCalculator.StringMaximumLength, "max_length"], [QgsAggregateCalculator.StringConcatenate, "concatenate"], [QgsAggregateCalculator.GeometryCollect, "collect"], ] for t in tests: agg, ok = QgsAggregateCalculator.stringToAggregate(t[1]) self.assertTrue(ok) self.assertEqual(agg, t[0]) # test some bad values agg, ok = QgsAggregateCalculator.stringToAggregate("") self.assertFalse(ok) agg, ok = QgsAggregateCalculator.stringToAggregate("bad") self.assertFalse(ok)
def testNumeric(self): """ Test calculation of aggregates on numeric fields""" layer = QgsVectorLayer("Point?field=fldint:integer&field=flddbl:double", "layer", "memory") pr = layer.dataProvider() # must be same length: int_values = [4, 2, 3, 2, 5, None, 8] dbl_values = [5.5, 3.5, 7.5, 5, 9, None, 7] self.assertEqual(len(int_values), len(dbl_values)) features = [] for i in range(len(int_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([int_values[i], dbl_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'fldint', 6], [QgsAggregateCalculator.Count, 'flddbl', 6], [QgsAggregateCalculator.Sum, 'fldint', 24], [QgsAggregateCalculator.Sum, 'flddbl', 37.5], [QgsAggregateCalculator.Mean, 'fldint', 4], [QgsAggregateCalculator.Mean, 'flddbl', 6.25], [QgsAggregateCalculator.StDev, 'fldint', 2.0816], [QgsAggregateCalculator.StDev, 'flddbl', 1.7969], [QgsAggregateCalculator.StDevSample, 'fldint', 2.2803], [QgsAggregateCalculator.StDevSample, 'flddbl', 1.9685], [QgsAggregateCalculator.Min, 'fldint', 2], [QgsAggregateCalculator.Min, 'flddbl', 3.5], [QgsAggregateCalculator.Max, 'fldint', 8], [QgsAggregateCalculator.Max, 'flddbl', 9], [QgsAggregateCalculator.Range, 'fldint', 6], [QgsAggregateCalculator.Range, 'flddbl', 5.5], [QgsAggregateCalculator.Median, 'fldint', 3.5], [QgsAggregateCalculator.Median, 'flddbl', 6.25], [QgsAggregateCalculator.CountDistinct, 'fldint', 5], [QgsAggregateCalculator.CountDistinct, 'flddbl', 6], [QgsAggregateCalculator.CountMissing, 'fldint', 1], [QgsAggregateCalculator.CountMissing, 'flddbl', 1], [QgsAggregateCalculator.FirstQuartile, 'fldint', 2], [QgsAggregateCalculator.FirstQuartile, 'flddbl', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'fldint', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'flddbl', 7.5], [QgsAggregateCalculator.InterQuartileRange, 'fldint', 3.0], [QgsAggregateCalculator.InterQuartileRange, 'flddbl', 2.5], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) if isinstance(t[2], int): self.assertEqual(val, t[2]) else: self.assertAlmostEqual(val, t[2], 3) # bad tests - the following stats should not be calculatable for numeric fields for t in [QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength]: val, ok = agg.calculate(t, 'fldint') self.assertFalse(ok) val, ok = agg.calculate(t, 'flddbl') self.assertFalse(ok)
def testExpression(self): """ test aggregate calculation using an expression """ # numeric layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) # int agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 48) # double val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 1.5') self.assertTrue(ok) self.assertEqual(val, 36) # datetime val, ok = agg.calculate( QgsAggregateCalculator.Max, "to_date('2012-05-04') + to_interval( fldint || ' day' )") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 12), QTime(0, 0, 0))) # date val, ok = agg.calculate( QgsAggregateCalculator.Min, "to_date(to_date('2012-05-04') + to_interval( fldint || ' day' ))") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 6), QTime(0, 0, 0))) # string val, ok = agg.calculate(QgsAggregateCalculator.Max, "fldint || ' oranges'") self.assertTrue(ok) self.assertEqual(val, '8 oranges') # geometry val, ok = agg.calculate(QgsAggregateCalculator.GeometryCollect, "make_point( coalesce(fldint,0), 2 )") self.assertTrue(ok) self.assertTrue(val.asWkt(), 'MultiPoint((4 2, 2 2, 3 2, 2 2,5 2, 0 2,8 2))') # try a bad expression val, ok = agg.calculate(QgsAggregateCalculator.Max, "not_a_field || ' oranges'") self.assertFalse(ok) val, ok = agg.calculate(QgsAggregateCalculator.Max, "5+") self.assertFalse(ok) # test expression context # check default context first # should have layer variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@layer_name") self.assertTrue(ok) self.assertEqual(val, 'layer') # but not custom variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var") self.assertTrue(ok) self.assertEqual(val, NULL) # test with manual expression context scope = QgsExpressionContextScope() scope.setVariable('my_var', 5) context = QgsExpressionContext() context.appendScope(scope) val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var", context) self.assertTrue(ok) self.assertEqual(val, 5)
def testExpressionNoMatch(self): """ test aggregate calculation using an expression with no features """ # no features layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") # sum agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, None) # count agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Count, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 0) # count distinct agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.CountDistinct, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 0) # count missing agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.CountMissing, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 0) # min agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Min, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, None) # max agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Max, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, None) # array_agg agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.ArrayAggregate, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, [])
def testNumeric(self): """ Test calculation of aggregates on numeric fields""" layer = QgsVectorLayer( "Point?field=fldint:integer&field=flddbl:double", "layer", "memory") pr = layer.dataProvider() # must be same length: int_values = [4, 2, 3, 2, 5, None, 8] dbl_values = [5.5, 3.5, 7.5, 5, 9, None, 7] self.assertEqual(len(int_values), len(dbl_values)) features = [] for i in range(len(int_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([int_values[i], dbl_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [ [QgsAggregateCalculator.Count, 'fldint', 6], [QgsAggregateCalculator.Count, 'flddbl', 6], [QgsAggregateCalculator.Sum, 'fldint', 24], [QgsAggregateCalculator.Sum, 'flddbl', 37.5], [QgsAggregateCalculator.Mean, 'fldint', 4], [QgsAggregateCalculator.Mean, 'flddbl', 6.25], [QgsAggregateCalculator.StDev, 'fldint', 2.0816], [QgsAggregateCalculator.StDev, 'flddbl', 1.7969], [QgsAggregateCalculator.StDevSample, 'fldint', 2.2803], [QgsAggregateCalculator.StDevSample, 'flddbl', 1.9685], [QgsAggregateCalculator.Min, 'fldint', 2], [QgsAggregateCalculator.Min, 'flddbl', 3.5], [QgsAggregateCalculator.Max, 'fldint', 8], [QgsAggregateCalculator.Max, 'flddbl', 9], [QgsAggregateCalculator.Range, 'fldint', 6], [QgsAggregateCalculator.Range, 'flddbl', 5.5], [QgsAggregateCalculator.Median, 'fldint', 3.5], [QgsAggregateCalculator.Median, 'flddbl', 6.25], [QgsAggregateCalculator.CountDistinct, 'fldint', 5], [QgsAggregateCalculator.CountDistinct, 'flddbl', 6], [QgsAggregateCalculator.CountMissing, 'fldint', 1], [QgsAggregateCalculator.CountMissing, 'flddbl', 1], [QgsAggregateCalculator.FirstQuartile, 'fldint', 2], [QgsAggregateCalculator.FirstQuartile, 'flddbl', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'fldint', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'flddbl', 7.5], [QgsAggregateCalculator.InterQuartileRange, 'fldint', 3.0], [QgsAggregateCalculator.InterQuartileRange, 'flddbl', 2.5], [QgsAggregateCalculator.ArrayAggregate, 'fldint', int_values], [QgsAggregateCalculator.ArrayAggregate, 'flddbl', dbl_values], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) if isinstance(t[2], (int, list)): self.assertEqual(val, t[2]) else: self.assertAlmostEqual(val, t[2], 3) # bad tests - the following stats should not be calculatable for numeric fields for t in [ QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength ]: val, ok = agg.calculate(t, 'fldint') self.assertFalse(ok) val, ok = agg.calculate(t, 'flddbl') self.assertFalse(ok)
def testExpression(self): """ test aggregate calculation using an expression """ # numeric layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) #int agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 48) # double val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 1.5') self.assertTrue(ok) self.assertEqual(val, 36) # datetime val, ok = agg.calculate(QgsAggregateCalculator.Max, "to_date('2012-05-04') + to_interval( fldint || ' day' )") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 12), QTime(0, 0, 0))) # date val, ok = agg.calculate(QgsAggregateCalculator.Min, "to_date(to_date('2012-05-04') + to_interval( fldint || ' day' ))") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 6), QTime(0, 0, 0))) # string val, ok = agg.calculate(QgsAggregateCalculator.Max, "fldint || ' oranges'") self.assertTrue(ok) self.assertEqual(val, '8 oranges') # geometry val, ok = agg.calculate(QgsAggregateCalculator.GeometryCollect, "make_point( coalesce(fldint,0), 2 )") self.assertTrue(ok) self.assertTrue(val.exportToWkt(), 'MultiPoint((4 2, 2 2, 3 2, 2 2,5 2, 0 2,8 2))') # try a bad expression val, ok = agg.calculate(QgsAggregateCalculator.Max, "not_a_field || ' oranges'") self.assertFalse(ok) val, ok = agg.calculate(QgsAggregateCalculator.Max, "5+") self.assertFalse(ok) # test expression context # check default context first # should have layer variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@layer_name") self.assertTrue(ok) self.assertEqual(val, 'layer') # but not custom variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var") self.assertTrue(ok) self.assertEqual(val, NULL) # test with manual expression context scope = QgsExpressionContextScope() scope.setVariable('my_var', 5) context = QgsExpressionContext() context.appendScope(scope) val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var", context) self.assertTrue(ok) self.assertEqual(val, 5)
def testDateTime(self): """ Test calculation of aggregates on date/datetime fields""" layer = QgsVectorLayer( "Point?field=flddate:date&field=flddatetime:datetime", "layer", "memory") pr = layer.dataProvider() # must be same length: datetime_values = [ QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), QDateTime(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), QDateTime(), QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54)) ] date_values = [ QDate(2015, 3, 4), QDate(2015, 3, 4), QDate(2019, 12, 28), QDate(), QDate(1998, 1, 2), QDate(), QDate(2011, 1, 5), QDate(2011, 1, 5), QDate(2011, 1, 5) ] self.assertEqual(len(datetime_values), len(date_values)) features = [] for i in range(len(datetime_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([date_values[i], datetime_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [ [QgsAggregateCalculator.Count, 'flddatetime', 9], [QgsAggregateCalculator.Count, 'flddate', 9], [QgsAggregateCalculator.CountDistinct, 'flddatetime', 6], [QgsAggregateCalculator.CountDistinct, 'flddate', 5], [QgsAggregateCalculator.CountMissing, 'flddatetime', 2], [QgsAggregateCalculator.CountMissing, 'flddate', 2], [ QgsAggregateCalculator.Min, 'flddatetime', QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)) ], [ QgsAggregateCalculator.Min, 'flddate', QDateTime(QDate(1998, 1, 2), QTime(0, 0, 0)) ], [ QgsAggregateCalculator.Max, 'flddatetime', QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)) ], [ QgsAggregateCalculator.Max, 'flddate', QDateTime(QDate(2019, 12, 28), QTime(0, 0, 0)) ], [ QgsAggregateCalculator.Range, 'flddatetime', QgsInterval(693871147) ], [QgsAggregateCalculator.Range, 'flddate', QgsInterval(693792000)], [ QgsAggregateCalculator.ArrayAggregate, 'flddatetime', [None if v.isNull() else v for v in datetime_values] ], [ QgsAggregateCalculator.ArrayAggregate, 'flddate', [None if v.isNull() else v for v in date_values] ], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # bad tests - the following stats should not be calculatable for string fields for t in [ QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Minority, QgsAggregateCalculator.Majority, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange, QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength, ]: val, ok = agg.calculate(t, 'flddatetime') self.assertFalse(ok)
def testDateTime(self): """ Test calculation of aggregates on date/datetime fields""" layer = QgsVectorLayer("Point?field=flddate:date&field=flddatetime:datetime", "layer", "memory") pr = layer.dataProvider() # must be same length: datetime_values = [QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), QDateTime(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), QDateTime(), QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))] date_values = [QDate(2015, 3, 4), QDate(2015, 3, 4), QDate(2019, 12, 28), QDate(), QDate(1998, 1, 2), QDate(), QDate(2011, 1, 5), QDate(2011, 1, 5), QDate(2011, 1, 5)] self.assertEqual(len(datetime_values), len(date_values)) features = [] for i in range(len(datetime_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([date_values[i], datetime_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'flddatetime', 9], [QgsAggregateCalculator.Count, 'flddate', 9], [QgsAggregateCalculator.CountDistinct, 'flddatetime', 6], [QgsAggregateCalculator.CountDistinct, 'flddate', 5], [QgsAggregateCalculator.CountMissing, 'flddatetime', 2], [QgsAggregateCalculator.CountMissing, 'flddate', 2], [QgsAggregateCalculator.Min, 'flddatetime', QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54))], [QgsAggregateCalculator.Min, 'flddate', QDateTime(QDate(1998, 1, 2), QTime(0, 0, 0))], [QgsAggregateCalculator.Max, 'flddatetime', QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1))], [QgsAggregateCalculator.Max, 'flddate', QDateTime(QDate(2019, 12, 28), QTime(0, 0, 0))], [QgsAggregateCalculator.Range, 'flddatetime', QgsInterval(693871147)], [QgsAggregateCalculator.Range, 'flddate', QgsInterval(693792000)], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # bad tests - the following stats should not be calculatable for string fields for t in [QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Minority, QgsAggregateCalculator.Majority, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange, QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength, ]: val, ok = agg.calculate(t, 'flddatetime') self.assertFalse(ok)
def testString(self): """ Test calculation of aggregates on string fields""" layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory") pr = layer.dataProvider() values = [ 'cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd' ] features = [] for v in values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) tests = [ [QgsAggregateCalculator.Count, 'fldstring', 9], [QgsAggregateCalculator.CountDistinct, 'fldstring', 6], [QgsAggregateCalculator.CountMissing, 'fldstring', 2], [QgsAggregateCalculator.Min, 'fldstring', 'aaaa'], [QgsAggregateCalculator.Max, 'fldstring', 'eeee'], [QgsAggregateCalculator.StringMinimumLength, 'fldstring', 0], [QgsAggregateCalculator.StringMaximumLength, 'fldstring', 8], [QgsAggregateCalculator.ArrayAggregate, 'fldstring', values], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # test string concatenation agg.setDelimiter(',') self.assertEqual(agg.delimiter(), ',') val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenate, 'fldstring') self.assertTrue(ok) self.assertEqual(val, 'cc,aaaa,bbbbbbbb,aaaa,eeee,,eeee,,dddd') val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenateUnique, 'fldstring') self.assertTrue(ok) self.assertEqual(val, 'cc,aaaa,bbbbbbbb,eeee,,dddd') # bad tests - the following stats should not be calculatable for string fields for t in [ QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Range, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange ]: val, ok = agg.calculate(t, 'fldstring') self.assertFalse(ok) # with order by agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.ArrayAggregate, 'fldstring') self.assertEqual( val, ['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd']) params = QgsAggregateCalculator.AggregateParameters() params.orderBy = QgsFeatureRequest.OrderBy( [QgsFeatureRequest.OrderByClause('fldstring')]) agg.setParameters(params) val, ok = agg.calculate(QgsAggregateCalculator.ArrayAggregate, 'fldstring') self.assertEqual( val, ['', '', 'aaaa', 'aaaa', 'bbbbbbbb', 'cc', 'dddd', 'eeee', 'eeee']) val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenate, 'fldstring') self.assertEqual(val, 'aaaaaaaabbbbbbbbccddddeeeeeeee') val, ok = agg.calculate(QgsAggregateCalculator.Minority, 'fldstring') self.assertEqual(val, 'bbbbbbbb') val, ok = agg.calculate(QgsAggregateCalculator.Majority, 'fldstring') self.assertEqual(val, '')