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')
Ejemplo n.º 2
0
    def testAggregate(self):
        """ Test aggregate calculation """
        layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory")
        pr = layer.dataProvider()

        int_values = [4, 2, 3, 2, 5, None, 8]
        features = []
        for i in int_values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([i])
            features.append(f)
        assert pr.addFeatures(features)

        tests = [[QgsAggregateCalculator.Count, 6],
                 [QgsAggregateCalculator.Sum, 24],
                 [QgsAggregateCalculator.Mean, 4],
                 [QgsAggregateCalculator.StDev, 2.0816],
                 [QgsAggregateCalculator.StDevSample, 2.2803],
                 [QgsAggregateCalculator.Min, 2],
                 [QgsAggregateCalculator.Max, 8],
                 [QgsAggregateCalculator.Range, 6],
                 [QgsAggregateCalculator.Median, 3.5],
                 [QgsAggregateCalculator.CountDistinct, 5],
                 [QgsAggregateCalculator.CountMissing, 1],
                 [QgsAggregateCalculator.FirstQuartile, 2],
                 [QgsAggregateCalculator.ThirdQuartile, 5.0],
                 [QgsAggregateCalculator.InterQuartileRange, 3.0]
                 ]

        for t in tests:
            val, ok = layer.aggregate(t[0], 'fldint')
            self.assertTrue(ok)
            if isinstance(t[1], int):
                self.assertEqual(val, t[1])
            else:
                self.assertAlmostEqual(val, t[1], 3)

        # test with parameters
        layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory")
        pr = layer.dataProvider()

        string_values = ['this', 'is', 'a', 'test']
        features = []
        for s in string_values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([s])
            features.append(f)
        assert pr.addFeatures(features)
        params = QgsAggregateCalculator.AggregateParameters()
        params.delimiter = ' '
        val, ok = layer.aggregate(QgsAggregateCalculator.StringConcatenate, 'fldstring', params)
        self.assertTrue(ok)
        self.assertEqual(val, 'this is a test')
    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)

        # with order by
        agg = QgsAggregateCalculator(layer)
        val, ok = agg.calculate(QgsAggregateCalculator.ArrayAggregate,
                                'fldint')
        self.assertEqual(val, [4, 2, 3, 2, 5, NULL, 8])
        params = QgsAggregateCalculator.AggregateParameters()
        params.orderBy = QgsFeatureRequest.OrderBy(
            [QgsFeatureRequest.OrderByClause('fldint')])
        agg.setParameters(params)
        val, ok = agg.calculate(QgsAggregateCalculator.ArrayAggregate,
                                'fldint')
        self.assertEqual(val, [2, 2, 3, 4, 5, 8, NULL])
        params.orderBy = QgsFeatureRequest.OrderBy(
            [QgsFeatureRequest.OrderByClause('flddbl')])
        agg.setParameters(params)
        val, ok = agg.calculate(QgsAggregateCalculator.ArrayAggregate,
                                'fldint')
        self.assertEqual(val, [2, 2, 4, 8, 3, 5, NULL])
    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)

        # 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')