diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 2d5d7120bfee9..e7d70ebb7b27f 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -1158,6 +1158,7 @@ Other - Bug in printing a :class:`DataFrame` with a :class:`DataFrame` stored in :attr:`DataFrame.attrs` raised a ``ValueError`` (:issue:`60455`) - Bug in printing a :class:`Series` with a :class:`DataFrame` stored in :attr:`Series.attrs` raised a ``ValueError`` (:issue:`60568`) - Deprecated the keyword ``check_datetimelike_compat`` in :meth:`testing.assert_frame_equal` and :meth:`testing.assert_series_equal` (:issue:`55638`) +- Fixed bug in the :meth:`Series.rank` with object dtype and extremely small float values (:issue:`62036`) - Fixed bug where the :class:`DataFrame` constructor misclassified array-like objects with a ``.name`` attribute as :class:`Series` or :class:`Index` (:issue:`61443`) - Fixed regression in :meth:`DataFrame.from_records` not initializing subclasses properly (:issue:`57008`) - diff --git a/pandas/_libs/algos.pyx b/pandas/_libs/algos.pyx index f584c0ff9f614..222b5b7952c2e 100644 --- a/pandas/_libs/algos.pyx +++ b/pandas/_libs/algos.pyx @@ -1,7 +1,6 @@ cimport cython from cython cimport Py_ssize_t from libc.math cimport ( - fabs, sqrt, ) from libc.stdlib cimport ( @@ -72,13 +71,6 @@ tiebreakers = { } -cdef bint are_diff(object left, object right): - try: - return fabs(left - right) > FP_ERR - except TypeError: - return left != right - - class Infinity: """ Provide a positive Infinity comparison method for ranking. @@ -1135,12 +1127,8 @@ cdef void rank_sorted_1d( dups += 1 sum_ranks += i - grp_start + 1 - if numeric_object_t is object: - next_val_diff = at_end or are_diff(masked_vals[sort_indexer[i]], - masked_vals[sort_indexer[i+1]]) - else: - next_val_diff = at_end or (masked_vals[sort_indexer[i]] - != masked_vals[sort_indexer[i+1]]) + next_val_diff = at_end or (masked_vals[sort_indexer[i]] + != masked_vals[sort_indexer[i+1]]) # We'll need this check later anyway to determine group size, so just # compute it here since shortcircuiting won't help diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index 5eef7cddfee41..c876aae6dea5e 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -1819,6 +1819,18 @@ def test_uint64_overflow(self, dtype): s = Series([1, 2**63], dtype=dtype) tm.assert_numpy_array_equal(algos.rank(s), exp) + @pytest.mark.parametrize("method", ["average", "min", "max"]) + def test_rank_tiny_values(self, method): + # GH62036: regression test for ranking with tiny float values + exp = np.array([4.0, 1.0, 3.0, np.nan, 2.0], dtype=np.float64) + s = Series( + [5.4954145e29, -9.791984e-21, 9.3715776e-26, pd.NA, 1.8790257e-28], + dtype="Float64", + ) + s = s.astype(object) + result = algos.rank(s, method=method) + tm.assert_numpy_array_equal(result, exp) + def test_too_many_ndims(self): arr = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]) msg = "Array with ndim > 2 are not supported"