Commit 06c38d68 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

RF: Force outputs of conditionals to be numpy arrays, so outputs from

different columns can be combined with binaey ops (as pandas won't combine
different columns with e.g. logical and)
parent b1c82935
......@@ -136,9 +136,10 @@ class Expression(object):
:arg dtable: The :class:`.DataTable` containing the data.
:arg data: Dictionary containing ``{ variable : column_name }``
:arg data: Dictionary containing ``{ variable : [column_name] }``
mappings from the variables used in the expressions to
columns in ``dtable``.
columns in ``dtable``. Each mapping may also contain a
single column name, instead of a list.
:returns: The outcome of the expression - ``True`` or ``False``.
......@@ -349,6 +350,9 @@ def parseVariable(toks):
return toks[1]
# conditionals are constructed to produce
# numpy arrays, so that is what these
# operations expect as inputs
def _not(op, *args): return ~op(*args) # noqa
def _and(op1, op2, *args): return op1(*args) & op2(*args) # noqa
def _or( op1, op2, *args): return op1(*args) | op2(*args) # noqa
......@@ -428,6 +432,20 @@ def _lt( var, val, dt, data): return dt[:, data[var]] < val # noqa
def _le( var, val, dt, data): return dt[:, data[var]] <= val # noqa
def _asarray(func, *args):
"""Calls ``func``, passing it ``*args``.
The return value of ``func`` is assumed to be a ``pandas.DataFrame``.
Its contents are converted to a ``numpy`` array.
This function is used by :func:`parseCondition` to construct functions
for evaluating conditional statements.
# DataFrame.to_numpy is only
# available in pandas >= 0.24
return func(*args).to_numpy()
def parseCondition(toks):
"""Parses a conditional statement of the form::
......@@ -439,6 +457,8 @@ def parseCondition(toks):
- ``value`` is a numeric value
Returns a function which can be used to evaluate the conditional statement.
The function is constructed such that it expects a ``pandas.DataFrame``,
and will output a boolean ``numpy`` array.
toks = toks[0]
variable = toks[0]
......@@ -456,7 +476,7 @@ def parseCondition(toks):
elif operation == SYMBOLS['le']: fn = _le
elif operation == SYMBOLS['lt']: fn = _lt
fn = ft.partial(fn, variable, value)
fn = ft.partial(_asarray, fn, variable, value)
fn.ftype = 'condition'
fn.operation = operation
fn.variable = variable
......@@ -676,6 +676,7 @@ def loadTableBases():
(101, 0) : util.CTYPES.compound,
# We need pandas >=0.24 to support enums here
def settype(valtype, basetype):
return typecodes[valtype, basetype]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment