From bd57c50d79a26e78fb7f94c91c8e6db40bb79617 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 27 Jan 2020 17:10:53 -0800 Subject: [PATCH 1/3] require values_from_object before expressions calls --- pandas/core/computation/expressions.py | 19 +++++-------------- pandas/core/internals/blocks.py | 8 +++++--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index ada983e9e4fad..51750b14dc585 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -12,8 +12,6 @@ from pandas._config import get_option -from pandas._libs.lib import values_from_object - from pandas.core.dtypes.generic import ABCDataFrame from pandas.core.computation.check import _NUMEXPR_INSTALLED @@ -123,26 +121,19 @@ def _evaluate_numexpr(op, op_str, a, b): def _where_standard(cond, a, b): - return np.where( - values_from_object(cond), values_from_object(a), values_from_object(b) - ) + # Caller is responsible for calling values_from_object if necessary + return np.where(cond, a, b) def _where_numexpr(cond, a, b): + # Caller is responsible for calling values_from_object if necessary result = None if _can_use_numexpr(None, "where", a, b, "where"): - cond_value = getattr(cond, "values", cond) - a_value = getattr(a, "values", a) - b_value = getattr(b, "values", b) result = ne.evaluate( "where(cond_value, a_value, b_value)", - local_dict={ - "cond_value": cond_value, - "a_value": a_value, - "b_value": b_value, - }, + local_dict={"cond_value": cond, "a_value": a, "b_value": b,}, casting="safe", ) @@ -187,7 +178,7 @@ def _bool_arith_check( return True -def evaluate(op, op_str, a, b, use_numexpr=True): +def evaluate(op, op_str, a, b, use_numexpr: bool = True): """ Evaluate and return the expression of the op on a and b. diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index a93211edf162b..80369081f96d6 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -1379,8 +1379,7 @@ def where( if not hasattr(cond, "shape"): raise ValueError("where must have a condition that is ndarray like") - # our where function - def func(cond, values, other): + def where_func(cond, values, other): if not ( (self.is_integer or self.is_bool) @@ -1391,8 +1390,11 @@ def func(cond, values, other): if not self._can_hold_element(other): raise TypeError if lib.is_scalar(other) and isinstance(values, np.ndarray): + # convert datetime to datetime64, timedelta to timedelta64 other = convert_scalar(values, other) + # By the time we get here, we should have all Series/Index + # args extracted to ndarray fastres = expressions.where(cond, values, other) return fastres @@ -1402,7 +1404,7 @@ def func(cond, values, other): # see if we can operate on the entire block, or need item-by-item # or if we are a single block (ndim == 1) try: - result = func(cond, values, other) + result = where_func(cond, values, other) except TypeError: # we cannot coerce, return a compat dtype From 058194589b1c858f367c94788cbe4f21667b9595 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 27 Jan 2020 17:11:52 -0800 Subject: [PATCH 2/3] lint --- pandas/core/computation/expressions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index 51750b14dc585..4ee2c993d112d 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -133,7 +133,7 @@ def _where_numexpr(cond, a, b): result = ne.evaluate( "where(cond_value, a_value, b_value)", - local_dict={"cond_value": cond, "a_value": a, "b_value": b,}, + local_dict={"cond_value": cond, "a_value": a, "b_value": b}, casting="safe", ) From 0060284dc57b341400fddda39bbee9c5a5b08b5e Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 27 Jan 2020 17:51:32 -0800 Subject: [PATCH 3/3] mypy fixup --- pandas/core/computation/expressions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index 4ee2c993d112d..fdc299ccdfde8 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -178,7 +178,7 @@ def _bool_arith_check( return True -def evaluate(op, op_str, a, b, use_numexpr: bool = True): +def evaluate(op, op_str, a, b, use_numexpr=True): """ Evaluate and return the expression of the op on a and b.