diff --git a/doc/whats-new.rst b/doc/whats-new.rst index f4dea1cd2aa..c8fbecf82af 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -36,6 +36,8 @@ Deprecations Bug fixes ~~~~~~~~~ +- Fix :py:class:`~xarray.groupers.BinGrouper` when ``labels`` is not specified (:issue:`10284`). + By `Deepak Cherian `_. - Allow accessing arbitrary attributes on Pandas ExtensionArrays. By `Deepak Cherian `_. diff --git a/xarray/groupers.py b/xarray/groupers.py index 203acbe37c5..226f98256f7 100644 --- a/xarray/groupers.py +++ b/xarray/groupers.py @@ -413,7 +413,7 @@ def factorize(self, group: T_Group) -> EncodedGroups: # This seems silly, but it lets us have Pandas handle the complexity # of `labels`, `precision`, and `include_lowest`, even when group is a chunked array # Pandas ignores labels when IntervalIndex is passed - if not isinstance(self.bins, pd.IntervalIndex): + if self.labels is None or not isinstance(self.bins, pd.IntervalIndex): dummy, _ = self._cut(np.array([0]).astype(group.dtype)) full_index = dummy.categories else: diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index fd5f2f5d6d1..0f260eb381d 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -1042,10 +1042,12 @@ def test_groupby_math_bitshift() -> None: assert_equal(right_expected, right_actual) +@pytest.mark.parametrize( + "x_bins", ((0, 2, 4, 6), pd.IntervalIndex.from_breaks((0, 2, 4, 6), closed="left")) +) @pytest.mark.parametrize("use_flox", [True, False]) -def test_groupby_bins_cut_kwargs(use_flox: bool) -> None: +def test_groupby_bins_cut_kwargs(use_flox: bool, x_bins) -> None: da = xr.DataArray(np.arange(12).reshape(6, 2), dims=("x", "y")) - x_bins = (0, 2, 4, 6) with xr.set_options(use_flox=use_flox): actual = da.groupby_bins( @@ -1055,7 +1057,12 @@ def test_groupby_bins_cut_kwargs(use_flox: bool) -> None: np.array([[1.0, 2.0], [5.0, 6.0], [9.0, 10.0]]), dims=("x_bins", "y"), coords={ - "x_bins": ("x_bins", pd.IntervalIndex.from_breaks(x_bins, closed="left")) + "x_bins": ( + "x_bins", + x_bins + if isinstance(x_bins, pd.IntervalIndex) + else pd.IntervalIndex.from_breaks(x_bins, closed="left"), + ) }, ) assert_identical(expected, actual) @@ -1067,9 +1074,8 @@ def test_groupby_bins_cut_kwargs(use_flox: bool) -> None: assert_identical(expected, actual) with xr.set_options(use_flox=use_flox): - bins_index = pd.IntervalIndex.from_breaks(x_bins) labels = ["one", "two", "three"] - actual = da.groupby(x=BinGrouper(bins=bins_index, labels=labels)).sum() + actual = da.groupby(x=BinGrouper(bins=x_bins, labels=labels)).sum() assert actual.xindexes["x_bins"].index.equals(pd.Index(labels)) # type: ignore[attr-defined]