22from __future__
import annotations
24__all__ = (
"makeColumnExpressionAction", )
29from typing
import Mapping, MutableMapping, Set, Type, Union, Optional, Any, Iterable
31from numpy
import log10
as log
32from numpy
import (cos, sin, cosh, sinh)
35from ..configurableActions
import ConfigurableActionField
36from ._baseDataFrameActions
import DataFrameAction
39OPERATORS = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
40 ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
43EXTRA_MATH = {
"cos": cos,
"sin": sin,
"cosh": cosh,
"sinh": sinh,
"log": log}
64 val = self.visit(node.operand)
65 return OPERATORS[
type(node.op)](val)
68 lhs = self.visit(node.left)
69 rhs = self.visit(node.right)
70 return OPERATORS[
type(node.op)](lhs, rhs)
73 if node.func.id
in self.
variablesvariables:
74 function = self.visit(node.func)
75 return function(self.visit(node.args[0]))
77 raise ValueError(
"String not recognized")
80 raise ValueError(
"String not recognized")
84 exprDefaults: Optional[Mapping[str, Union[DataFrameAction,
85 Type[DataFrameAction]]]] =
None,
87 ) -> Type[DataFrameAction]:
88 """Factory function for producing ConfigurableAction classes which are
89 realizations of arithmetic operations.
94 The name of the class that will be produced
96 An arithmetic expression that will be parsed to produce the output
97 ConfigurableAction. Individual variable names will be the name of
98 individual `ConfigActions` inside the expression (i.e.
"x+y" will
99 produce an action
with configAction.actions.x
and
100 configAction.actions.y). Expression can contain arithmatic python
101 operators
as well
as; sin, cos, sinh, cosh, log (which
is base 10).
102 exprDefaults : `Mapping` of `str` to `DataFrameAction` optional
103 A mapping of strings which correspond to the names
in the expression to
104 values which are default `ConfigurableActions` to assign
in the
105 expression. If no default
for a action
is supplied `SingleColumnAction`
106 is set
as the default.
108 A string that
is assigned
as the resulting classes docstring
112 action : `Type` of `DataFrameAction`
113 A `DataFrameAction`
class that was programatically constructed
from the
121 new_module = inspect.stack()[1].frame.f_locals[
'__name__']
122 node = ast.parse(expr, mode=
'eval')
125 names: Set[str] =
set()
126 for elm
in ast.walk(node):
127 if isinstance(elm, ast.Name):
131 names -= EXTRA_MATH.keys()
133 fields: Mapping[str, ConfigurableActionField] = {}
135 if exprDefaults
is not None and (value := exprDefaults.get(name))
is not None:
136 kwargs = {
"default": value}
143 def __call__(self, df: pd.DataFrame, **kwargs) -> pd.Series:
146 values_map[name] = getattr(self, name)(df, **kwargs)
149 return parser.visit(node.body)
152 def columns(self) -> Iterable[str]:
154 yield from getattr(self, name).columns
156 dct: MutableMapping[str, Any] = {
"__call__": __call__,
"columns": property(columns)}
157 if docstring
is not None:
158 dct[
'__doc__'] = docstring
160 dct[
'__module__'] = new_module
162 return type(className, (DataFrameAction, ), dct)
def visit_NameConstant(self, node)
def visit_UnaryOp(self, node)
def visit_Num(self, node)
def visit_Call(self, node)
def __init__(self, **kwargs)
def visit_BinOp(self, node)
def visit_Name(self, node)
def generic_visit(self, node)
daf::base::PropertySet * set
Type[DataFrameAction] makeColumnExpressionAction(str className, str expr, Optional[Mapping[str, Union[DataFrameAction, Type[DataFrameAction]]]] exprDefaults=None, str docstring=None)