From 8588651d8479d6ef908114480e54900b6020d700 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Wed, 17 Mar 2021 22:10:35 +0100 Subject: [PATCH] REF/PERF: move np.errstate out of core array_ops up to higher level (#40396) --- pandas/core/arrays/numpy_.py | 3 ++- pandas/core/computation/expressions.py | 3 +-- pandas/core/frame.py | 36 ++++++++++++++------------ pandas/core/ops/array_ops.py | 18 +++++++------ pandas/core/series.py | 6 +++-- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index 89988349132e6..45656459792ba 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -376,7 +376,8 @@ def _cmp_method(self, other, op): other = other._ndarray pd_op = ops.get_array_op(op) - result = pd_op(self._ndarray, other) + with np.errstate(all="ignore"): + result = pd_op(self._ndarray, other) if op is divmod or op is ops.rdivmod: a, b = result diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index 05736578b6337..0dbe5e8d83741 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -71,8 +71,7 @@ def _evaluate_standard(op, op_str, a, b): """ if _TEST_MODE: _store_test_result(False) - with np.errstate(all="ignore"): - return op(a, b) + return op(a, b) def _can_use_numexpr(op, op_str, a, b, dtype_check): diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 2374cc0b6a8fa..b1f0ad8eda2aa 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -6643,7 +6643,8 @@ def _dispatch_frame_op(self, right, func: Callable, axis: Optional[int] = None): right = lib.item_from_zerodim(right) if not is_list_like(right): # i.e. scalar, faster than checking np.ndim(right) == 0 - bm = self._mgr.apply(array_op, right=right) + with np.errstate(all="ignore"): + bm = self._mgr.apply(array_op, right=right) return type(self)(bm) elif isinstance(right, DataFrame): @@ -6654,16 +6655,17 @@ def _dispatch_frame_op(self, right, func: Callable, axis: Optional[int] = None): # _frame_arith_method_with_reindex # TODO operate_blockwise expects a manager of the same type - bm = self._mgr.operate_blockwise( - # error: Argument 1 to "operate_blockwise" of "ArrayManager" has - # incompatible type "Union[ArrayManager, BlockManager]"; expected - # "ArrayManager" - # error: Argument 1 to "operate_blockwise" of "BlockManager" has - # incompatible type "Union[ArrayManager, BlockManager]"; expected - # "BlockManager" - right._mgr, # type: ignore[arg-type] - array_op, - ) + with np.errstate(all="ignore"): + bm = self._mgr.operate_blockwise( + # error: Argument 1 to "operate_blockwise" of "ArrayManager" has + # incompatible type "Union[ArrayManager, BlockManager]"; expected + # "ArrayManager" + # error: Argument 1 to "operate_blockwise" of "BlockManager" has + # incompatible type "Union[ArrayManager, BlockManager]"; expected + # "BlockManager" + right._mgr, # type: ignore[arg-type] + array_op, + ) return type(self)(bm) elif isinstance(right, Series) and axis == 1: @@ -6674,16 +6676,18 @@ def _dispatch_frame_op(self, right, func: Callable, axis: Optional[int] = None): # maybe_align_as_frame ensures we do not have an ndarray here assert not isinstance(right, np.ndarray) - arrays = [ - array_op(_left, _right) - for _left, _right in zip(self._iter_column_arrays(), right) - ] + with np.errstate(all="ignore"): + arrays = [ + array_op(_left, _right) + for _left, _right in zip(self._iter_column_arrays(), right) + ] elif isinstance(right, Series): assert right.index.equals(self.index) # Handle other cases later right = right._values - arrays = [array_op(left, right) for left in self._iter_column_arrays()] + with np.errstate(all="ignore"): + arrays = [array_op(left, right) for left in self._iter_column_arrays()] else: # Remaining cases have less-obvious dispatch rules diff --git a/pandas/core/ops/array_ops.py b/pandas/core/ops/array_ops.py index 6f6972c34f0a9..04737d91c0d4e 100644 --- a/pandas/core/ops/array_ops.py +++ b/pandas/core/ops/array_ops.py @@ -106,8 +106,7 @@ def _masked_arith_op(x: np.ndarray, y, op): # See GH#5284, GH#5035, GH#19448 for historical reference if mask.any(): - with np.errstate(all="ignore"): - result[mask] = op(xrav[mask], yrav[mask]) + result[mask] = op(xrav[mask], yrav[mask]) else: if not is_scalar(y): @@ -126,8 +125,7 @@ def _masked_arith_op(x: np.ndarray, y, op): mask = np.where(y == 1, False, mask) if mask.any(): - with np.errstate(all="ignore"): - result[mask] = op(xrav[mask], y) + result[mask] = op(xrav[mask], y) result = maybe_upcast_putmask(result, ~mask) result = result.reshape(x.shape) # 2D compat @@ -179,6 +177,9 @@ def arithmetic_op(left: ArrayLike, right: Any, op): """ Evaluate an arithmetic operation `+`, `-`, `*`, `/`, `//`, `%`, `**`, ... + Note: the caller is responsible for ensuring that numpy warnings are + suppressed (with np.errstate(all="ignore")) if needed. + Parameters ---------- left : np.ndarray or ExtensionArray @@ -206,8 +207,7 @@ def arithmetic_op(left: ArrayLike, right: Any, op): res_values = op(lvalues, rvalues) else: - with np.errstate(all="ignore"): - res_values = _na_arithmetic_op(lvalues, rvalues, op) + res_values = _na_arithmetic_op(lvalues, rvalues, op) return res_values @@ -216,6 +216,9 @@ def comparison_op(left: ArrayLike, right: Any, op) -> ArrayLike: """ Evaluate a comparison operation `=`, `!=`, `>=`, `>`, `<=`, or `<`. + Note: the caller is responsible for ensuring that numpy warnings are + suppressed (with np.errstate(all="ignore")) if needed. + Parameters ---------- left : np.ndarray or ExtensionArray @@ -267,8 +270,7 @@ def comparison_op(left: ArrayLike, right: Any, op) -> ArrayLike: with warnings.catch_warnings(): # suppress warnings from numpy about element-wise comparison warnings.simplefilter("ignore", DeprecationWarning) - with np.errstate(all="ignore"): - res_values = _na_arithmetic_op(lvalues, rvalues, op, is_cmp=True) + res_values = _na_arithmetic_op(lvalues, rvalues, op, is_cmp=True) return res_values diff --git a/pandas/core/series.py b/pandas/core/series.py index 662c7abb33e33..83eb4c38bc163 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -5087,7 +5087,8 @@ def _cmp_method(self, other, op): lvalues = self._values rvalues = extract_array(other, extract_numpy=True) - res_values = ops.comparison_op(lvalues, rvalues, op) + with np.errstate(all="ignore"): + res_values = ops.comparison_op(lvalues, rvalues, op) return self._construct_result(res_values, name=res_name) @@ -5107,7 +5108,8 @@ def _arith_method(self, other, op): lvalues = self._values rvalues = extract_array(other, extract_numpy=True) - result = ops.arithmetic_op(lvalues, rvalues, op) + with np.errstate(all="ignore"): + result = ops.arithmetic_op(lvalues, rvalues, op) return self._construct_result(result, name=res_name)