-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcolumn_from_expression.py
150 lines (112 loc) · 5.05 KB
/
column_from_expression.py
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import orca
import pandas as pd
from urbansim_templates import modelmanager, shared, utils, __version__
from urbansim_templates.shared import CoreTemplateSettings, OutputColumnSettings
class ExpressionSettings():
"""
Stores custom parameters used by the
:mod:`~urbansim_templates.data.ColumnFromExpression` template. Parameters can be
passed to the constructor or set as attributes.
Parameters
----------
table : str, optional
Name of Orca table the expression will be evaluated on. Required before running
then template.
expression : str, optional
String describing operations on existing columns of the table, for example
"a/log(b+c)". Required before running. Supports arithmetic and math functions
including sqrt, abs, log, log1p, exp, and expm1 -- see Pandas ``df.eval()``
documentation for further details.
"""
def __init__(self, table = None, expression = None):
self.table = table
self.expression = expression
@classmethod
def from_dict(cls, d):
return cls(table=d['table'], expression=d['expression'])
def to_dict(self):
return {'table': self.table, 'expression': self.expression}
@modelmanager.template
class ColumnFromExpression():
"""
Template to register a column of derived data with Orca, based on an expression.
Parameters may be passed to the constructor, but they are easier to set as
attributes. The expression can refer to any columns in the same table, and will be
evaluated using ``df.eval()``. Values will be calculated lazily, only when the column
is needed for a specific operation.
Parameters
----------
meta : :mod:`~urbansim_templates.shared.CoreTemplateSettings`, optional
Standard parameters. This template sets the default value of ``meta.autorun``
to True.
data : :mod:`~urbansim_templates.data.ExpressionSettings`, optional
Special parameters for this template.
output : :mod:`~urbansim_templates.shared.OutputColumnSettings`, optional
Parameters for the column that will be generated. This template uses
``data.table`` as the default value for ``output.table``.
"""
def __init__(self, meta=None, data=None, output=None):
self.meta = CoreTemplateSettings(autorun=True) if meta is None else meta
self.meta.template = self.__class__.__name__
self.meta.template_version = __version__
self.data = ExpressionSettings() if data is None else data
self.output = OutputColumnSettings() if output is None else output
@classmethod
def from_dict(cls, d):
"""
Create a class instance from a saved dictionary.
"""
if 'meta' not in d:
return cls.from_dict_0_2_dev5(d)
return cls(
meta = CoreTemplateSettings.from_dict(d['meta']),
data = ExpressionSettings.from_dict(d['data']),
output = OutputColumnSettings.from_dict(d['output']))
@classmethod
def from_dict_0_2_dev5(cls, d):
"""
Converter to read saved data from 0.2.dev5 or earlier. Automatically invoked by
``from_dict()`` as needed.
"""
return cls(
meta = CoreTemplateSettings(
name = d['name'],
tags = d['tags'],
autorun = d['autorun']),
data = ExpressionSettings(
table = d['table'],
expression = d['expression']),
output = OutputColumnSettings(
column_name = d['column_name'],
data_type = d['data_type'],
missing_values = d['missing_values'],
cache = d['cache'],
cache_scope = d['cache_scope']))
def to_dict(self):
"""
Create a dictionary representation of the object.
"""
return {
'meta': self.meta.to_dict(),
'data': self.data.to_dict(),
'output': self.output.to_dict()}
def run(self):
"""
Run the template, registering a column of derived data with Orca. Requires values
to be set for ``data.table``, ``data.expression``, and ``output.column_name``.
"""
if self.data.table is None:
raise ValueError("Please provide a table")
if self.data.expression is None:
raise ValueError("Please provide an expression")
if self.output.column_name is None:
raise ValueError("Please provide a column name")
settings = self.output
if settings.table is None:
settings.table = self.data.table
cols = utils.cols_in_expression(self.data.expression)
def build_column():
df = utils.get_df(self.data.table, columns=cols)
series = df.eval(self.data.expression)
return series
shared.register_column(build_column, settings)