File: percent.py

package info (click to toggle)
python-agate 1.9.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,996 kB
  • sloc: python: 8,512; makefile: 126
file content (72 lines) | stat: -rw-r--r-- 2,486 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from agate.aggregations.has_nulls import HasNulls
from agate.aggregations.sum import Sum
from agate.computations.base import Computation
from agate.data_types import Number
from agate.exceptions import DataTypeError
from agate.warns import warn_null_calculation


class Percent(Computation):
    """
    Calculate each values percentage of a total.

    :param column_name:
        The name of a column containing the :class:`.Number` values.
    :param total:
        If specified, the total value for each number to be divided into. By
        default, the :class:`.Sum` of the values in the column will be used.
    """
    def __init__(self, column_name, total=None):
        self._column_name = column_name
        self._total = total

    def get_computed_data_type(self, table):
        return Number()

    def validate(self, table):
        column = table.columns[self._column_name]

        if not isinstance(column.data_type, Number):
            raise DataTypeError('Percent column must contain Number data.')
        if self._total is not None and self._total <= 0:
            raise DataTypeError('The total must be a positive number')

        # Throw a warning if there are nulls in there
        if HasNulls(self._column_name).run(table):
            warn_null_calculation(self, column)

    def run(self, table):
        """
        :returns:
            :class:`decimal.Decimal`
        """
        # If the user has provided a total, use that
        if self._total is not None:
            total = self._total
        # Otherwise compute the sum of all the values in that column to
        # act as our denominator
        else:
            total = table.aggregate(Sum(self._column_name))
            # Raise error if sum is less than or equal to zero
            if total <= 0:
                raise DataTypeError('The sum of column values must be a positive number')

        # Create a list new rows
        new_column = []

        # Loop through the existing rows
        for row in table.rows:
            # Pull the value
            value = row[self._column_name]
            if value is None:
                new_column.append(None)
                continue
            # Try to divide it out of the total
            percent = value / total
            # And multiply it by 100
            percent = percent * 100
            # Append the value to the new list
            new_column.append(percent)

        # Pass out the list
        return new_column