Total Complexity | 41 |
Total Lines | 153 |
Duplicated Lines | 0 % |
Complex classes like Orange.statistics.Discrete often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | import random |
||
33 | class Discrete(np.ndarray): |
||
34 | def __new__(cls, dat, variable=None, unknowns=None): |
||
35 | if isinstance(dat, data.Storage): |
||
36 | if unknowns is not None: |
||
37 | raise TypeError( |
||
38 | "incompatible arguments (data storage and 'unknowns'") |
||
39 | return cls.from_data(dat, variable) |
||
40 | |||
41 | if variable is not None: |
||
42 | variable = _get_variable(dat, variable) |
||
43 | n = len(variable.values) |
||
44 | else: |
||
45 | n = len(dat) |
||
46 | |||
47 | self = super().__new__(cls, n) |
||
48 | self.variable = variable |
||
49 | if dat is None: |
||
50 | self[:] = 0 |
||
51 | self.unknowns = unknowns or 0 |
||
52 | else: |
||
53 | self[:] = dat |
||
54 | self.unknowns = (unknowns if unknowns is not None |
||
55 | else getattr(dat, "unknowns", 0)) |
||
56 | return self |
||
57 | |||
58 | |||
59 | @classmethod |
||
60 | def from_data(cls, data, variable): |
||
61 | variable = _get_variable(data, variable) |
||
62 | try: |
||
63 | dist, unknowns = data._compute_distributions([variable])[0] |
||
64 | self = super().__new__(cls, len(dist)) |
||
65 | self[:] = dist |
||
66 | self.unknowns = unknowns |
||
67 | except NotImplementedError: |
||
68 | self = super().__new__(cls, len(variable.values)) |
||
69 | self[:] = np.zeros(len(variable.values)) |
||
70 | self.unknowns = 0 |
||
71 | if data.has_weights(): |
||
72 | for val, w in zip(data[:, variable], data.W): |
||
73 | if not math.isnan(val): |
||
74 | self[val] += w |
||
75 | else: |
||
76 | self.unknowns += w |
||
77 | else: |
||
78 | for inst in data: |
||
79 | val = inst[variable] |
||
80 | if val == val: |
||
81 | self[val] += 1 |
||
82 | else: |
||
83 | self.unknowns += 1 |
||
84 | self.variable = variable |
||
85 | return self |
||
86 | |||
87 | |||
88 | def __eq__(self, other): |
||
89 | return np.array_equal(self, other) and ( |
||
90 | not hasattr(other, "unknowns") or self.unknowns == other.unknowns) |
||
91 | |||
92 | def __ne__(self, other): |
||
93 | return not self == other |
||
94 | |||
95 | def __getitem__(self, index): |
||
96 | if isinstance(index, str): |
||
97 | index = self.variable.to_val(index) |
||
98 | return super().__getitem__(index) |
||
99 | |||
100 | |||
101 | def __setitem__(self, index, value): |
||
102 | if isinstance(index, str): |
||
103 | index = self.variable.to_val(index) |
||
104 | super().__setitem__(index, value) |
||
105 | |||
106 | |||
107 | def __hash__(self): |
||
108 | return zlib.adler32(self) ^ hash(self.unknowns) |
||
109 | |||
110 | |||
111 | def __add__(self, other): |
||
112 | s = super().__add__(other) |
||
113 | s.unknowns = self.unknowns + getattr(other, "unknowns", 0) |
||
114 | return s |
||
115 | |||
116 | |||
117 | def __iadd__(self, other): |
||
118 | super().__iadd__(other) |
||
119 | self.unknowns += getattr(other, "unknowns", 0) |
||
120 | return self |
||
121 | |||
122 | |||
123 | def __sub__(self, other): |
||
124 | s = super().__sub__(other) |
||
125 | s.unknowns = self.unknowns - getattr(other, "unknowns", 0) |
||
126 | return s |
||
127 | |||
128 | |||
129 | def __isub__(self, other): |
||
130 | super().__isub__(other) |
||
131 | self.unknowns -= getattr(other, "unknowns", 0) |
||
132 | return self |
||
133 | |||
134 | |||
135 | def __mul__(self, other): |
||
136 | s = super().__mul__(other) |
||
137 | if isinstance(other, Real): |
||
138 | s.unknowns = self.unknowns / other |
||
139 | return s |
||
140 | |||
141 | |||
142 | def __imul__(self, other): |
||
143 | super().__imul__(other) |
||
144 | if isinstance(other, Real): |
||
145 | self.unknowns *= other |
||
146 | return self |
||
147 | |||
148 | |||
149 | def __div__(self, other): |
||
150 | s = super().__mul__(other) |
||
151 | if isinstance(other, Real): |
||
152 | s.unknowns = self.unknowns / other |
||
153 | return s |
||
154 | |||
155 | |||
156 | def __idiv__(self, other): |
||
157 | super().__imul__(other) |
||
158 | if isinstance(other, Real): |
||
159 | self.unknowns /= other |
||
160 | return self |
||
161 | |||
162 | |||
163 | def normalize(self): |
||
164 | t = np.sum(self) |
||
165 | if t > 1e-6: |
||
166 | self[:] /= t |
||
167 | self.unknowns /= t |
||
168 | elif self.shape[0]: |
||
169 | self[:] = 1 / self.shape[0] |
||
170 | |||
171 | |||
172 | def modus(self): |
||
173 | val = np.argmax(self) |
||
174 | return data.Value(self.variable, |
||
175 | val) if self.variable is not None else val |
||
176 | |||
177 | |||
178 | def random(self): |
||
179 | v = random.random() * np.sum(self) |
||
180 | s = i = 0 |
||
181 | for i, e in enumerate(self): |
||
182 | s += e |
||
183 | if s > v: |
||
184 | break |
||
185 | return data.Value(self.variable, i) if self.variable is not None else i |
||
186 | |||
350 |
This can be caused by one of the following:
1. Missing Dependencies
This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.
2. Missing __init__.py files
This error could also result from missing
__init__.py
files in your module folders. Make sure that you place one file in each sub-folder.