From 5ded786f5b3d8931d3523e5cd5b4dacec8eeca3d Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 2 Apr 2021 20:47:50 +0200 Subject: [PATCH 01/15] Add failing test. --- pandas/tests/groupby/test_function.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pandas/tests/groupby/test_function.py b/pandas/tests/groupby/test_function.py index 515774eae009b..25c533a69c028 100644 --- a/pandas/tests/groupby/test_function.py +++ b/pandas/tests/groupby/test_function.py @@ -1131,3 +1131,11 @@ def test_groupby_sum_below_mincount_nullable_integer(): result = grouped.sum(min_count=2) expected = DataFrame({"b": [pd.NA] * 3, "c": [pd.NA] * 3}, dtype="Int64", index=idx) tm.assert_frame_equal(result, expected) + + +def test_groupby_index_object_dtype(): + # GH 40014 + df = DataFrame({"c0": ["x", "x", "x"], "c1": ["x", "x", "y"], "p": [0, 1, 2]}) + df.index = df.index.astype("O") + grouped = df.groupby(["c0", "c1"]) + grouped.p.agg(lambda x: all(x > 0)) From 04d61b51a17fd7754d86bbdbf5e5de7055a031f5 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Thu, 8 Apr 2021 15:56:48 +0200 Subject: [PATCH 02/15] Dont use fastpath for series whith object index. --- pandas/core/groupby/ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/groupby/ops.py b/pandas/core/groupby/ops.py index 5bf9f81e3073d..59dfb085cf630 100644 --- a/pandas/core/groupby/ops.py +++ b/pandas/core/groupby/ops.py @@ -738,7 +738,7 @@ def agg_series(self, obj: Series, func: F): # TODO: can we get a performant workaround for EAs backed by ndarray? return self._aggregate_series_pure_python(obj, func) - elif obj.index._has_complex_internals: + elif obj.index._has_complex_internals or obj.index.dtype == "object": # Preempt TypeError in _aggregate_series_fast return self._aggregate_series_pure_python(obj, func) From d4d9fb578f725ad38258ea6f24ad194519c3d994 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 9 Apr 2021 09:53:18 +0200 Subject: [PATCH 03/15] Add comment. --- pandas/core/groupby/ops.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/core/groupby/ops.py b/pandas/core/groupby/ops.py index 59dfb085cf630..60af768fb1d7a 100644 --- a/pandas/core/groupby/ops.py +++ b/pandas/core/groupby/ops.py @@ -739,7 +739,11 @@ def agg_series(self, obj: Series, func: F): return self._aggregate_series_pure_python(obj, func) elif obj.index._has_complex_internals or obj.index.dtype == "object": - # Preempt TypeError in _aggregate_series_fast + # (complex internals): Preempt TypeError in _aggregate_series_fast + # (object index dtype): _aggregate_series_fast raises TypeError + # when applying func because the group indiced become malformatted: + # correct indices are in group.index._index_data, but not in + # group.index._data. return self._aggregate_series_pure_python(obj, func) try: From 307bbe519f618fcdf3dcf877965ac6832144c735 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 9 Apr 2021 10:03:36 +0200 Subject: [PATCH 04/15] Add whatsnew --- doc/source/whatsnew/v1.2.4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.4.rst b/doc/source/whatsnew/v1.2.4.rst index 9cef1307278e8..e13a834a2934f 100644 --- a/doc/source/whatsnew/v1.2.4.rst +++ b/doc/source/whatsnew/v1.2.4.rst @@ -29,7 +29,7 @@ Fixed regressions Bug fixes ~~~~~~~~~ -- +- Bug in groupby aggregation when using an object-typed index (issue:`40014`) - .. --------------------------------------------------------------------------- From bb7f09efe19ad98adebf336d56b56fe5ca589444 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 9 Apr 2021 10:13:25 +0200 Subject: [PATCH 05/15] Move test. --- pandas/tests/groupby/aggregate/test_aggregate.py | 8 ++++++++ pandas/tests/groupby/test_function.py | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pandas/tests/groupby/aggregate/test_aggregate.py b/pandas/tests/groupby/aggregate/test_aggregate.py index fc0b4d86e81bf..b42d041882ca7 100644 --- a/pandas/tests/groupby/aggregate/test_aggregate.py +++ b/pandas/tests/groupby/aggregate/test_aggregate.py @@ -1221,3 +1221,11 @@ def test_aggregate_numeric_object_dtype(): {"key": ["A", "B"], "col1": ["a", "c"], "col2": [0, 2]} ).set_index("key") tm.assert_frame_equal(result, expected) + + +def test_groupby_index_object_dtype(): + # GH 40014 + df = DataFrame({"c0": ["x", "x", "x"], "c1": ["x", "x", "y"], "p": [0, 1, 2]}) + df.index = df.index.astype("O") + grouped = df.groupby(["c0", "c1"]) + grouped.p.agg(lambda x: all(x > 0)) diff --git a/pandas/tests/groupby/test_function.py b/pandas/tests/groupby/test_function.py index 51cb65093b95f..843d438018a32 100644 --- a/pandas/tests/groupby/test_function.py +++ b/pandas/tests/groupby/test_function.py @@ -1087,11 +1087,3 @@ def test_groupby_sum_below_mincount_nullable_integer(): result = grouped.sum(min_count=2) expected = DataFrame({"b": [pd.NA] * 3, "c": [pd.NA] * 3}, dtype="Int64", index=idx) tm.assert_frame_equal(result, expected) - - -def test_groupby_index_object_dtype(): - # GH 40014 - df = DataFrame({"c0": ["x", "x", "x"], "c1": ["x", "x", "y"], "p": [0, 1, 2]}) - df.index = df.index.astype("O") - grouped = df.groupby(["c0", "c1"]) - grouped.p.agg(lambda x: all(x > 0)) From 4f318374d17709f464696428de5a2607ad33d6b3 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 9 Apr 2021 10:30:25 +0200 Subject: [PATCH 06/15] Check test expected result. --- pandas/tests/groupby/aggregate/test_aggregate.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandas/tests/groupby/aggregate/test_aggregate.py b/pandas/tests/groupby/aggregate/test_aggregate.py index b42d041882ca7..0ee705f9cd68f 100644 --- a/pandas/tests/groupby/aggregate/test_aggregate.py +++ b/pandas/tests/groupby/aggregate/test_aggregate.py @@ -1228,4 +1228,9 @@ def test_groupby_index_object_dtype(): df = DataFrame({"c0": ["x", "x", "x"], "c1": ["x", "x", "y"], "p": [0, 1, 2]}) df.index = df.index.astype("O") grouped = df.groupby(["c0", "c1"]) - grouped.p.agg(lambda x: all(x > 0)) + res = grouped.p.agg(lambda x: all(x > 0)) + expected_index = MultiIndex.from_tuples( + [("x", "x"), ("x", "y")], names=("c0", "c1") + ) + expected = Series([False, True], index=expected_index, name="p") + tm.assert_series_equal(res, expected) From db9b29bcc04300fdce2e3a3a867418614bc1c46d Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 9 Apr 2021 13:53:37 +0200 Subject: [PATCH 07/15] Move whatsnew --- doc/source/whatsnew/v1.2.4.rst | 2 +- doc/source/whatsnew/v1.3.0.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.4.rst b/doc/source/whatsnew/v1.2.4.rst index e13a834a2934f..9cef1307278e8 100644 --- a/doc/source/whatsnew/v1.2.4.rst +++ b/doc/source/whatsnew/v1.2.4.rst @@ -29,7 +29,7 @@ Fixed regressions Bug fixes ~~~~~~~~~ -- Bug in groupby aggregation when using an object-typed index (issue:`40014`) +- - .. --------------------------------------------------------------------------- diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 3a0e1b7568c91..54b453f80b072 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -763,6 +763,7 @@ Groupby/resample/rolling - :class:`core.window.ewm.ExponentialMovingWindow` now raises a ``NotImplementedError`` when specifying ``times`` with ``adjust=False`` due to an incorrect calculation (:issue:`40098`) - Bug in :meth:`Series.asfreq` and :meth:`DataFrame.asfreq` dropping rows when the index is not sorted (:issue:`39805`) - Bug in aggregation functions for :class:`DataFrame` not respecting ``numeric_only`` argument when ``level`` keyword was given (:issue:`40660`) +- Bug in groupby aggregation when using an object-typed index (issue:`40014`) Reshaping ^^^^^^^^^ From b0dfbcd9238d04aa2c5a589fc6d17b4232e163f5 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Fri, 9 Apr 2021 22:35:15 +0200 Subject: [PATCH 08/15] Adjustment for review --- doc/source/whatsnew/v1.3.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 515dc3320bee2..e40f1ce598f5e 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -780,7 +780,7 @@ Groupby/resample/rolling - :class:`core.window.ewm.ExponentialMovingWindow` now raises a ``NotImplementedError`` when specifying ``times`` with ``adjust=False`` due to an incorrect calculation (:issue:`40098`) - Bug in :meth:`Series.asfreq` and :meth:`DataFrame.asfreq` dropping rows when the index is not sorted (:issue:`39805`) - Bug in aggregation functions for :class:`DataFrame` not respecting ``numeric_only`` argument when ``level`` keyword was given (:issue:`40660`) -- Bug in groupby aggregation when using an object-typed index (issue:`40014`) +- Bug in groupby aggregation when using an object-typed :class:`Index` (issue:`40014`) - Bug in :class:`core.window.RollingGroupby` where ``as_index=False`` argument in ``groupby`` was ignored (:issue:`39433`) Reshaping From a21be6f608e429fe7516f59ad1e851826b066fc7 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Mon, 12 Apr 2021 10:33:38 +0200 Subject: [PATCH 09/15] New solution. --- pandas/_libs/reduction.pyx | 2 +- pandas/core/groupby/ops.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pandas/_libs/reduction.pyx b/pandas/_libs/reduction.pyx index 9acff1cac305c..085b915a5fed8 100644 --- a/pandas/_libs/reduction.pyx +++ b/pandas/_libs/reduction.pyx @@ -55,7 +55,7 @@ cdef class _BaseGrouper: cdef inline _update_cached_objs(self, object cached_typ, object cached_ityp, Slider islider, Slider vslider): - if cached_typ is None: + if cached_typ is None or len(islider) != len(cached_ityp): cached_ityp = self.ityp(islider.buf) cached_typ = self.typ( vslider.buf, dtype=vslider.buf.dtype, index=cached_ityp, name=self.name diff --git a/pandas/core/groupby/ops.py b/pandas/core/groupby/ops.py index 60af768fb1d7a..5bf9f81e3073d 100644 --- a/pandas/core/groupby/ops.py +++ b/pandas/core/groupby/ops.py @@ -738,12 +738,8 @@ def agg_series(self, obj: Series, func: F): # TODO: can we get a performant workaround for EAs backed by ndarray? return self._aggregate_series_pure_python(obj, func) - elif obj.index._has_complex_internals or obj.index.dtype == "object": - # (complex internals): Preempt TypeError in _aggregate_series_fast - # (object index dtype): _aggregate_series_fast raises TypeError - # when applying func because the group indiced become malformatted: - # correct indices are in group.index._index_data, but not in - # group.index._data. + elif obj.index._has_complex_internals: + # Preempt TypeError in _aggregate_series_fast return self._aggregate_series_pure_python(obj, func) try: From 4bf3f2001b1116daf260174bf13db4d245194700 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Mon, 12 Apr 2021 11:25:22 +0200 Subject: [PATCH 10/15] Fix len error. --- pandas/_libs/reduction.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/reduction.pyx b/pandas/_libs/reduction.pyx index 085b915a5fed8..33944f8e3653f 100644 --- a/pandas/_libs/reduction.pyx +++ b/pandas/_libs/reduction.pyx @@ -55,7 +55,7 @@ cdef class _BaseGrouper: cdef inline _update_cached_objs(self, object cached_typ, object cached_ityp, Slider islider, Slider vslider): - if cached_typ is None or len(islider) != len(cached_ityp): + if cached_typ is None or len(vslider.buf) != len(cached_ityp): cached_ityp = self.ityp(islider.buf) cached_typ = self.typ( vslider.buf, dtype=vslider.buf.dtype, index=cached_ityp, name=self.name From 0c16e6c5e42fedd2bd0a9f0b8d826bcbf1bd2733 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Mon, 12 Apr 2021 20:54:15 +0200 Subject: [PATCH 11/15] Fix index caching. --- pandas/_libs/reduction.pyx | 5 +++-- pandas/tests/groupby/test_bin_groupby.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/reduction.pyx b/pandas/_libs/reduction.pyx index 33944f8e3653f..ae58b6770884e 100644 --- a/pandas/_libs/reduction.pyx +++ b/pandas/_libs/reduction.pyx @@ -55,7 +55,7 @@ cdef class _BaseGrouper: cdef inline _update_cached_objs(self, object cached_typ, object cached_ityp, Slider islider, Slider vslider): - if cached_typ is None or len(vslider.buf) != len(cached_ityp): + if cached_typ is None: cached_ityp = self.ityp(islider.buf) cached_typ = self.typ( vslider.buf, dtype=vslider.buf.dtype, index=cached_ityp, name=self.name @@ -65,12 +65,12 @@ cdef class _BaseGrouper: # We need this for EA-backed indexes that have a reference # to a 1-d ndarray like datetime / timedelta / period. object.__setattr__(cached_ityp, '_index_data', islider.buf) + object.__setattr__(cached_ityp, '_data', islider.buf) cached_ityp._engine.clear_mapping() cached_ityp._cache.clear() # e.g. inferred_freq must go cached_typ._mgr.set_values(vslider.buf) object.__setattr__(cached_typ, '_index', cached_ityp) object.__setattr__(cached_typ, 'name', self.name) - return cached_typ, cached_ityp cdef inline object _apply_to_group(self, @@ -259,6 +259,7 @@ cdef class SeriesGrouper(_BaseGrouper): start += group_size group_size = 0 continue + print(f"Group size: {group_size}") end = start + group_size islider.move(start, end) diff --git a/pandas/tests/groupby/test_bin_groupby.py b/pandas/tests/groupby/test_bin_groupby.py index 5fcf4a73479a5..22021e5235235 100644 --- a/pandas/tests/groupby/test_bin_groupby.py +++ b/pandas/tests/groupby/test_bin_groupby.py @@ -27,6 +27,21 @@ def test_series_grouper(): tm.assert_almost_equal(counts, exp_counts) +def test_series_grouper_result_length_difference(): + obj = Series(np.random.randn(10), dtype="float64") + obj.index = obj.index.astype("O") + labels = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1, 1], dtype=np.intp) + + grouper = libreduction.SeriesGrouper(obj, lambda x: all(x > 0), labels, 2) + result, counts = grouper.get_result() + + expected = np.array([all(obj[3:6] > 0), all(obj[6:] > 0)]) + tm.assert_almost_equal(result, expected) + + exp_counts = np.array([3, 4], dtype=np.int64) + tm.assert_almost_equal(counts, exp_counts) + + def test_series_grouper_requires_nonempty_raises(): # GH#29500 obj = Series(np.random.randn(10)) From 3eb7b797cb261f7240d68b82eb0171f7623067f4 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Tue, 13 Apr 2021 10:20:43 +0200 Subject: [PATCH 12/15] Fix index caching (2) --- pandas/_libs/reduction.pyx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/reduction.pyx b/pandas/_libs/reduction.pyx index ae58b6770884e..78664a464ef72 100644 --- a/pandas/_libs/reduction.pyx +++ b/pandas/_libs/reduction.pyx @@ -56,7 +56,7 @@ cdef class _BaseGrouper: cdef inline _update_cached_objs(self, object cached_typ, object cached_ityp, Slider islider, Slider vslider): if cached_typ is None: - cached_ityp = self.ityp(islider.buf) + cached_ityp = self.ityp(islider.buf, dtype=self.idtype) cached_typ = self.typ( vslider.buf, dtype=vslider.buf.dtype, index=cached_ityp, name=self.name ) @@ -65,7 +65,6 @@ cdef class _BaseGrouper: # We need this for EA-backed indexes that have a reference # to a 1-d ndarray like datetime / timedelta / period. object.__setattr__(cached_ityp, '_index_data', islider.buf) - object.__setattr__(cached_ityp, '_data', islider.buf) cached_ityp._engine.clear_mapping() cached_ityp._cache.clear() # e.g. inferred_freq must go cached_typ._mgr.set_values(vslider.buf) @@ -107,6 +106,7 @@ cdef class SeriesBinGrouper(_BaseGrouper): cdef public: ndarray arr, index, dummy_arr, dummy_index object values, f, bins, typ, ityp, name + object idtype def __init__(self, object series, object f, object bins): @@ -122,6 +122,7 @@ cdef class SeriesBinGrouper(_BaseGrouper): self.arr = values self.typ = series._constructor self.ityp = series.index._constructor + self.idtype = series.index.dtype self.index = series.index.values self.name = series.name @@ -200,6 +201,7 @@ cdef class SeriesGrouper(_BaseGrouper): cdef public: ndarray arr, index, dummy_arr, dummy_index object f, labels, values, typ, ityp, name + object idtype def __init__(self, object series, object f, ndarray[intp_t] labels, Py_ssize_t ngroups): @@ -218,6 +220,7 @@ cdef class SeriesGrouper(_BaseGrouper): self.arr = values self.typ = series._constructor self.ityp = series.index._constructor + self.idtype = series.index.dtype self.index = series.index.values self.name = series.name From 86db8705b1cfc812dde34e8cf6d4cf7f2589255a Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Tue, 13 Apr 2021 11:28:22 +0200 Subject: [PATCH 13/15] Styling and remove stray print statement --- pandas/_libs/reduction.pyx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pandas/_libs/reduction.pyx b/pandas/_libs/reduction.pyx index 78664a464ef72..ec0678cd87f7e 100644 --- a/pandas/_libs/reduction.pyx +++ b/pandas/_libs/reduction.pyx @@ -105,8 +105,7 @@ cdef class SeriesBinGrouper(_BaseGrouper): cdef public: ndarray arr, index, dummy_arr, dummy_index - object values, f, bins, typ, ityp, name - object idtype + object values, f, bins, typ, ityp, name, idtype def __init__(self, object series, object f, object bins): @@ -200,8 +199,7 @@ cdef class SeriesGrouper(_BaseGrouper): cdef public: ndarray arr, index, dummy_arr, dummy_index - object f, labels, values, typ, ityp, name - object idtype + object f, labels, values, typ, ityp, name, idtype def __init__(self, object series, object f, ndarray[intp_t] labels, Py_ssize_t ngroups): @@ -262,7 +260,6 @@ cdef class SeriesGrouper(_BaseGrouper): start += group_size group_size = 0 continue - print(f"Group size: {group_size}") end = start + group_size islider.move(start, end) From ded84333c8d625efa970a4676ef5075875bfa048 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Tue, 13 Apr 2021 16:21:14 +0200 Subject: [PATCH 14/15] Adjustments for review --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/tests/groupby/aggregate/test_aggregate.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 9ec31c36844e2..caf9948a947a1 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -781,7 +781,7 @@ Groupby/resample/rolling - :class:`core.window.ewm.ExponentialMovingWindow` now raises a ``NotImplementedError`` when specifying ``times`` with ``adjust=False`` due to an incorrect calculation (:issue:`40098`) - Bug in :meth:`Series.asfreq` and :meth:`DataFrame.asfreq` dropping rows when the index is not sorted (:issue:`39805`) - Bug in aggregation functions for :class:`DataFrame` not respecting ``numeric_only`` argument when ``level`` keyword was given (:issue:`40660`) -- Bug in groupby aggregation when using an object-typed :class:`Index` (issue:`40014`) +- Bug in :meth:`SeriesGroupBy.aggregate` where using a user-defined function to aggregate a ``Series`` with an object-typed :class:`Index` causes an incorrect :class:`Index` shape (issue:`40014`) - Bug in :class:`core.window.RollingGroupby` where ``as_index=False`` argument in ``groupby`` was ignored (:issue:`39433`) Reshaping diff --git a/pandas/tests/groupby/aggregate/test_aggregate.py b/pandas/tests/groupby/aggregate/test_aggregate.py index 0ee705f9cd68f..28344897a686f 100644 --- a/pandas/tests/groupby/aggregate/test_aggregate.py +++ b/pandas/tests/groupby/aggregate/test_aggregate.py @@ -1229,6 +1229,8 @@ def test_groupby_index_object_dtype(): df.index = df.index.astype("O") grouped = df.groupby(["c0", "c1"]) res = grouped.p.agg(lambda x: all(x > 0)) + # Check that providing a user-defined function in agg() + # produces the correct index shape when using an object-typed index. expected_index = MultiIndex.from_tuples( [("x", "x"), ("x", "y")], names=("c0", "c1") ) From b89eee0d4d653c6b5f9b7b3bb6b5f12a77b2d583 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Wed, 14 Apr 2021 09:12:53 +0200 Subject: [PATCH 15/15] Add issue number, change almost_equal to assert_equal --- pandas/tests/groupby/test_bin_groupby.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/tests/groupby/test_bin_groupby.py b/pandas/tests/groupby/test_bin_groupby.py index 22021e5235235..13fddad30eeba 100644 --- a/pandas/tests/groupby/test_bin_groupby.py +++ b/pandas/tests/groupby/test_bin_groupby.py @@ -28,6 +28,7 @@ def test_series_grouper(): def test_series_grouper_result_length_difference(): + # GH 40014 obj = Series(np.random.randn(10), dtype="float64") obj.index = obj.index.astype("O") labels = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1, 1], dtype=np.intp) @@ -36,10 +37,10 @@ def test_series_grouper_result_length_difference(): result, counts = grouper.get_result() expected = np.array([all(obj[3:6] > 0), all(obj[6:] > 0)]) - tm.assert_almost_equal(result, expected) + tm.assert_equal(result, expected) exp_counts = np.array([3, 4], dtype=np.int64) - tm.assert_almost_equal(counts, exp_counts) + tm.assert_equal(counts, exp_counts) def test_series_grouper_requires_nonempty_raises():