diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index ffa65032e6aae..c098a3b2443c4 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -951,6 +951,7 @@ Missing ^^^^^^^ - Bug in :meth:`DataFrame.fillna` and :meth:`Series.fillna` that would ignore the ``limit`` argument on :class:`.ExtensionArray` dtypes (:issue:`58001`) - Bug in :meth:`NA.__and__`, :meth:`NA.__or__` and :meth:`NA.__xor__` when operating with ``np.bool_`` objects (:issue:`58427`) +- Bug in ``divmod`` between :class:`NA` and ``Int64`` dtype objects (:issue:`62196`) - MultiIndex diff --git a/pandas/core/arrays/masked.py b/pandas/core/arrays/masked.py index ce7f288fc0238..b00e362e1309a 100644 --- a/pandas/core/arrays/masked.py +++ b/pandas/core/arrays/masked.py @@ -791,6 +791,10 @@ def _arith_method(self, other, op): # will be all-True, but since this is division, we want # to end up with floating dtype. result = result.astype(np.float64) + elif op_name in {"divmod", "rdivmod"}: + # GH#62196 + res = self._maybe_mask_result(result, mask) + return res, res.copy() else: # Make sure we do this before the "pow" mask checks # to get an expected exception message on shape mismatch. diff --git a/pandas/tests/arrays/masked/test_arithmetic.py b/pandas/tests/arrays/masked/test_arithmetic.py index ea018d2da4d26..779531d525505 100644 --- a/pandas/tests/arrays/masked/test_arithmetic.py +++ b/pandas/tests/arrays/masked/test_arithmetic.py @@ -246,3 +246,26 @@ def test_unary_op_does_not_propagate_mask(data, op): expected = result.copy(deep=True) ser[0] = None tm.assert_series_equal(result, expected) + + +@pytest.mark.parametrize("dtype", ["Int64", "Int32", "Float32", "Float64"]) +def test_divmod_pdna(dtype): + # GH#62196 + ser = pd.Series([1, 2, 3], dtype=dtype) + res = divmod(pd.NA, ser) + assert isinstance(res, tuple) and len(res) == 2 + + exp = pd.Series([pd.NA, pd.NA, pd.NA], dtype=dtype) + tm.assert_series_equal(res[0], exp) + tm.assert_series_equal(res[1], exp) + + tm.assert_series_equal(res[0], pd.NA // ser) + tm.assert_series_equal(res[1], pd.NA % ser) + + res = divmod(ser, pd.NA) + assert isinstance(res, tuple) and len(res) == 2 + tm.assert_series_equal(res[0], exp) + tm.assert_series_equal(res[1], exp) + + tm.assert_series_equal(res[0], ser // pd.NA) + tm.assert_series_equal(res[1], ser % pd.NA)