From 7e6bd38306613888a94813e66136bd4e844f7c4b Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 1 Apr 2021 14:38:50 +0200 Subject: [PATCH 1/2] REF: only fallback to masked op for object dtype --- pandas/core/computation/expressions.py | 15 ++++++++++----- pandas/core/ops/array_ops.py | 12 +++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index 8205534c9d48b..4430420eab8b1 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -104,11 +104,16 @@ def _evaluate_numexpr(op, op_str, a, b): a_value = a b_value = b - result = ne.evaluate( - f"a_value {op_str} b_value", - local_dict={"a_value": a_value, "b_value": b_value}, - casting="safe", - ) + try: + result = ne.evaluate( + f"a_value {op_str} b_value", + local_dict={"a_value": a_value, "b_value": b_value}, + casting="safe", + ) + except TypeError: + # numexpr raises eg for array ** array with integers + # (https://github.com/pydata/numexpr/issues/379) + pass if _TEST_MODE: _store_test_result(result is not None) diff --git a/pandas/core/ops/array_ops.py b/pandas/core/ops/array_ops.py index 1d7c16de0c05d..5c26377f44c2b 100644 --- a/pandas/core/ops/array_ops.py +++ b/pandas/core/ops/array_ops.py @@ -158,12 +158,14 @@ def _na_arithmetic_op(left, right, op, is_cmp: bool = False): try: result = expressions.evaluate(op, left, right) except TypeError: - if is_cmp: - # numexpr failed on comparison op, e.g. ndarray[float] > datetime - # In this case we do not fall back to the masked op, as that - # will handle complex numbers incorrectly, see GH#32047 + if is_object_dtype(left) or is_object_dtype(right) and not is_cmp: + # For object dtype, fallback to a masked operation (only operating + # on the non-missing values) + # Don't do this for comparisons, as that will handle complex numbers + # incorrectly, see GH#32047 + result = _masked_arith_op(left, right, op) + else: raise - result = _masked_arith_op(left, right, op) if is_cmp and (is_scalar(result) or result is NotImplemented): # numpy returned a scalar instead of operating element-wise From 83448eb1366848d622341580c9551587c5441b7b Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 1 Apr 2021 20:34:39 +0200 Subject: [PATCH 2/2] fix reverse --- pandas/core/computation/expressions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index 4430420eab8b1..957a493925405 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -115,6 +115,10 @@ def _evaluate_numexpr(op, op_str, a, b): # (https://github.com/pydata/numexpr/issues/379) pass + if is_reversed: + # reverse order to original for fallback + a, b = b, a + if _TEST_MODE: _store_test_result(result is not None)