Passed
Push — master ( 5f2d49...176334 )
by Konstantinos
49s queued 12s
created

BinnerFactory.equal_length_binner()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 3
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
from abc import ABC
2
import attr
3
from so_magic.utils import SubclassRegistry
4
5
6
class DiscretizerInterface(ABC):
7
    def discretize(self, *args, **kwargs):
8
        raise NotImplementedError
9
10
11
class AbstractDiscretizer(DiscretizerInterface):
12
    def discretize(self, *args, **kwargs):
13
        raise NotImplementedError
14
15
16
def validate_bin_function(_self, _attribute, value):
17
    if not callable(value):
18
        raise ValueError(f'Expected a callable object, instead a {type(value).__name__} was given.')
19
20
@attr.s
21
class BaseDiscretizer(AbstractDiscretizer):
22
    binner = attr.ib(init=True, validator=validate_bin_function)
23
24
    def discretize(self, *args, **kwargs):
25
        """Expects args: dataset, feature and kwargs; 'nb_bins'."""
26
        dataset, feature, nb_bins = args[0], args[1], args[2]
27
        return self.binner(feature.values(dataset), nb_bins)
28
29
30
@attr.s
31
class FeatureDiscretizer(BaseDiscretizer):
32
    feature = attr.ib(init=True)
33
34
    def discretize(self, *args, **kwargs):
35
        """Expects args: dataset, nb_bins."""
36
        return super().discretize(args[0], self.feature, args[1])
37
38
@attr.s
39
class FeatureDiscretizerFactory:
40
    binner_factory = attr.ib(init=True)
41
42
    def categorical(self, feature, **kwargs) -> FeatureDiscretizer:
43
        binner_type = 'same-length'
44
        if kwargs.get('quantisized', False):
45
            binner_type = 'quantisized'
46
        return FeatureDiscretizer(self.binner_factory.create_binner(binner_type), feature)
47
48
    def numerical(self, feature, **kwargs) -> FeatureDiscretizer:
49
        binner_type = 'same-length'
50
        if kwargs.get('quantisized', False):
51
            binner_type = 'quantisized'
52
        return FeatureDiscretizer(self.binner_factory.create_binner(binner_type), feature)
53
54
55
#########################################
56
57
class BinnerInterface(ABC):
58
    def bin(self, values, nb_bins):
59
        raise NotImplementedError
60
61
62
class BaseBinner(BinnerInterface):
63
64
    def bin(self, values, nb_bins):
65
        """It is assumed numerical (ratio or interval) variable or ordinal (not nominal) categorical variable."""
66
        raise NotImplementedError
67
68
69
class BinnerClass(metaclass=SubclassRegistry): pass
70
71
72
class BinnerFactory:
73
    parent_class = BinnerClass
74
75
    def equal_length_binner(self, *args, **kwargs) -> BaseBinner:
76
        raise NotImplementedError
77
78
    def quantisized_binner(self, *args, **kwargs) -> BaseBinner:
79
        raise NotImplementedError
80
81
    def create_binner(self, *args, **kwargs) -> BaseBinner:
82
        raise NotImplementedError
83