/ src / evidently / legacy / utils / types.py
types.py
 1  """Additional types, classes, dataclasses, etc."""
 2  
 3  from typing import Any
 4  from typing import ClassVar
 5  from typing import Dict
 6  from typing import Optional
 7  from typing import Union
 8  
 9  from evidently.pydantic_utils import ExcludeNoneMixin
10  from evidently.pydantic_utils import FrozenBaseModel
11  
12  Numeric = Union[float, int]
13  
14  # type for distributions - list of tuples (value, count)
15  ColumnDistribution = Dict[Any, Numeric]
16  
17  
18  class ApproxValue(FrozenBaseModel, ExcludeNoneMixin):
19      """Class for approximate scalar value calculations"""
20  
21      class Config:
22          smart_union = True
23  
24      DEFAULT_RELATIVE: ClassVar = 1e-6
25      DEFAULT_ABSOLUTE: ClassVar = 1e-12
26  
27      value: Numeric
28      relative: Numeric
29      absolute: Numeric
30  
31      def __init__(self, value: Numeric, relative: Optional[Numeric] = None, absolute: Optional[Numeric] = None):
32          if relative is not None and relative <= 0:
33              raise ValueError("Relative value for approx should be greater than 0")
34  
35          if relative is None:
36              relative = self.DEFAULT_RELATIVE
37  
38          if absolute is None:
39              absolute = self.DEFAULT_ABSOLUTE
40  
41          super().__init__(value=value, relative=relative, absolute=absolute)
42  
43      @property
44      def tolerance(self) -> Numeric:
45          relative_value = abs(self.value) * self.relative
46          return max(relative_value, self.absolute)
47  
48      def __format__(self, format_spec):
49          return f"{format(self.value, format_spec)} ± {format(self.tolerance, format_spec)}"
50  
51      def __repr__(self):
52          return f"{self.value} ± {self.tolerance}"
53  
54      def __eq__(self, other):
55          tolerance = self.tolerance
56          return (self.value - tolerance) <= other <= (self.value + tolerance)
57  
58      def __lt__(self, other):
59          return self.value + self.tolerance < other
60  
61      def __le__(self, other):
62          return self.value - self.tolerance <= other
63  
64      def __gt__(self, other):
65          return self.value - self.tolerance > other
66  
67      def __ge__(self, other):
68          return self.value + self.tolerance >= other
69  
70  
71  NumericApprox = Union[int, float, ApproxValue]