From 1c7076f63eb974488967d934508c910f706b4648 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 21 Feb 2023 12:18:09 -0800 Subject: [PATCH 1/2] ENH: pyarrow dont raise on division by zero --- pandas/core/arrays/arrow/array.py | 6 +++--- pandas/tests/extension/test_arrow.py | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index eeb252b10b1ea..ab4f87d4cf374 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -106,7 +106,7 @@ def floordiv_compat( ) -> pa.ChunkedArray: # Ensure int // int -> int mirroring Python/Numpy behavior # as pc.floor(pc.divide_checked(int, int)) -> float - result = pc.floor(pc.divide_checked(left, right)) + result = pc.floor(pc.divide(left, right)) if pa.types.is_integer(left.type) and pa.types.is_integer(right.type): result = result.cast(left.type) return result @@ -118,8 +118,8 @@ def floordiv_compat( "rsub": lambda x, y: pc.subtract_checked(y, x), "mul": pc.multiply_checked, "rmul": lambda x, y: pc.multiply_checked(y, x), - "truediv": lambda x, y: pc.divide_checked(cast_for_truediv(x, y), y), - "rtruediv": lambda x, y: pc.divide_checked(y, cast_for_truediv(x, y)), + "truediv": lambda x, y: pc.divide(cast_for_truediv(x, y), y), + "rtruediv": lambda x, y: pc.divide(y, cast_for_truediv(x, y)), "floordiv": lambda x, y: floordiv_compat(x, y), "rfloordiv": lambda x, y: floordiv_compat(y, x), "mod": NotImplemented, diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 705e9d55c06e7..75e5744f498b4 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -888,6 +888,16 @@ def test_basic_equals(self, data): class TestBaseArithmeticOps(base.BaseArithmeticOpsTests): divmod_exc = NotImplementedError + def get_op_from_name(self, op_name): + short_opname = op_name.strip("_") + if short_opname == "rtruediv": + # use the numpy version that won't raise on division by zero + return lambda x, y: np.divide(y, x) + elif short_opname == "rfloordiv": + return lambda x, y: np.floor_divide(y, x) + + return tm.get_op_from_name(op_name) + def _patch_combine(self, obj, other, op): # BaseOpsUtil._combine can upcast expected dtype # (because it generates expected on python scalars) @@ -988,8 +998,8 @@ def _get_arith_xfail_marker(self, opname, pa_dtype): ), ) elif ( - opname in {"__rtruediv__", "__rfloordiv__"} - and (pa.types.is_floating(pa_dtype) or pa.types.is_integer(pa_dtype)) + opname in {"__rfloordiv__"} + and pa.types.is_integer(pa_dtype) and not pa_version_under7p0 ): mark = pytest.mark.xfail( @@ -1105,7 +1115,7 @@ def test_arith_series_with_array( pa.types.is_floating(pa_dtype) or ( pa.types.is_integer(pa_dtype) - and all_arithmetic_operators != "__truediv__" + and all_arithmetic_operators not in ["__truediv__", "__rtruediv__"] ) or pa.types.is_duration(pa_dtype) or pa.types.is_timestamp(pa_dtype) From ea078c33f288d573eec1c5c7f0782605f89c0b9e Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 21 Feb 2023 15:37:14 -0800 Subject: [PATCH 2/2] Whatsnew --- doc/source/whatsnew/v2.0.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index c0082b451c95d..45a5d139349e9 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -814,6 +814,7 @@ Other API changes - :func:`to_datetime` with ``unit`` of either "Y" or "M" will now raise if a sequence contains a non-round ``float`` value, matching the ``Timestamp`` behavior (:issue:`50301`) - The methods :meth:`Series.round`, :meth:`DataFrame.__invert__`, :meth:`Series.__invert__`, :meth:`DataFrame.swapaxes`, :meth:`DataFrame.first`, :meth:`DataFrame.last`, :meth:`Series.first`, :meth:`Series.last` and :meth:`DataFrame.align` will now always return new objects (:issue:`51032`) - :class:`DataFrame` and :class:`DataFrameGroupBy` aggregations (e.g. "sum") with object-dtype columns no longer infer non-object dtypes for their results, explicitly call ``result.infer_objects(copy=False)`` on the result to obtain the old behavior (:issue:`51205`, :issue:`49603`) +- Division by zero with :class:`ArrowDtype` dtypes returns ``-inf``, ``nan``, or ``inf`` depending on the numerator, instead of raising (:issue:`51541`) - Added :func:`pandas.api.types.is_any_real_numeric_dtype` to check for real numeric dtypes (:issue:`51152`) .. note::