diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index b16ca0a80c5b4..aaec5da8af66f 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -157,7 +157,7 @@ ExtensionArray Other ^^^^^ -- +- Bug in :meth:`Series.rank` incorrectly treating int64 min value as NaN (:issue:`32859`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_libs/algos.pyx b/pandas/_libs/algos.pyx index 7e90a8cc681ef..958cbd050ed61 100644 --- a/pandas/_libs/algos.pyx +++ b/pandas/_libs/algos.pyx @@ -840,7 +840,7 @@ def rank_1d( elif rank_t is float64_t: mask = np.isnan(values) elif rank_t is int64_t: - mask = values == NPY_NAT + mask = missing.isnaobj(values) # create copy in case of NPY_NAT # values are mutated inplace diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index 6c6bdb6b1b2bd..6e656eca5e152 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -1769,6 +1769,19 @@ def test_basic(self): s = Series([1, 100], dtype=dtype) tm.assert_numpy_array_equal(algos.rank(s), exp) + @pytest.mark.parametrize("dtype", ["int32", "int64"]) + def test_negative_min_rank(self, dtype): + # GH#32859 + # Check that nan is respected on float64 + s = pd.Series(np.array([np.inf, np.nan, -np.inf])) + expected = pd.Series(np.array([2.0, np.nan, 1.0])) + tm.assert_series_equal(s.rank(na_option="keep"), expected) + + # Rank works if coverted to most negative value + s = pd.Series(np.array([np.inf, np.nan, -np.inf]).astype(dtype)) + expected = pd.Series(np.array([2.0, 2.0, 2.0])) + tm.assert_series_equal(s.rank(na_option="keep"), expected) + def test_uint64_overflow(self): exp = np.array([1, 2], dtype=np.float64)