Skip to content

Commit 08fbb41

Browse files
committed
Fix recombination in groupby when changing size along the grouped dimension
1 parent b6c8162 commit 08fbb41

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

doc/whats-new.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ New Features
3535
Bug fixes
3636
~~~~~~~~~
3737

38+
- Fix recombination of groups in :py:meth:`Dataset.groupby` and
39+
:py:meth:`DataArray.groupby` when performing an operation that changes the
40+
size of the groups along the grouped dimension. By `Eric Jansen
41+
<https://github.com/ej81>`_.
3842
- Fix :py:meth:`Dataset.swap_dims` and :py:meth:`DataArray.swap_dims` producing
3943
index with name reflecting the previous dimension name instead of the new one
4044
(:issue:`3748`, :pull:`3752`). By `Joseph K Aicher

xarray/core/groupby.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ def assign_coords(self, coords=None, **coords_kwargs):
715715
def _maybe_reorder(xarray_obj, dim, positions):
716716
order = _inverse_permutation_indices(positions)
717717

718-
if order is None:
718+
if order is None or len(order) != xarray_obj.sizes[dim]:
719719
return xarray_obj
720720
else:
721721
return xarray_obj[{dim: order}]
@@ -833,7 +833,7 @@ def _combine(self, applied, restore_coord_dims=False, shortcut=False):
833833
if isinstance(combined, type(self._obj)):
834834
# only restore dimension order for arrays
835835
combined = self._restore_dim_order(combined)
836-
if coord is not None:
836+
if coord is not None and applied_example.sizes.get(dim, 0) == 0:
837837
if shortcut:
838838
coord_var = as_variable(coord)
839839
combined._coords[coord.name] = coord_var
@@ -949,7 +949,7 @@ def _combine(self, applied):
949949
coord, dim, positions = self._infer_concat_args(applied_example)
950950
combined = concat(applied, dim)
951951
combined = _maybe_reorder(combined, dim, positions)
952-
if coord is not None:
952+
if coord is not None and applied_example.sizes.get(dim, 0) == 0:
953953
combined[coord.name] = coord
954954
combined = self._maybe_restore_empty_groups(combined)
955955
combined = self._maybe_unstack(combined)

xarray/tests/test_groupby.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,50 @@ def test_groupby_input_mutation():
107107
assert_identical(array, array_copy) # should not modify inputs
108108

109109

110+
def test_da_groupby_map_shrink_groups():
111+
array = xr.DataArray([1, 2, 3, 4, 5, 6], [("x", [1, 1, 1, 2, 2, 2])])
112+
expected = array.isel(x=[0, 1, 3, 4])
113+
actual = array.groupby("x").map(lambda f: f.isel(x=[0, 1]))
114+
assert_identical(expected, actual)
115+
116+
117+
def test_ds_groupby_map_shrink_groups():
118+
dataset = xr.Dataset({"foo": ("x", [1, 2, 3, 4, 5, 6])}, {"x": [1, 1, 1, 2, 2, 2]})
119+
expected = dataset.isel(x=[0, 1, 3, 4])
120+
actual = dataset.groupby("x").map(lambda f: f.isel(x=[0, 1]))
121+
assert_identical(expected, actual)
122+
123+
124+
def test_da_groupby_map_change_group_size():
125+
array = xr.DataArray([1, 2, 3], [("x", [1, 2, 2])])
126+
127+
def func(group):
128+
if group.sizes["x"] == 1:
129+
result = group.isel(x=[0, 0])
130+
else:
131+
result = group.isel(x=[0])
132+
return result
133+
134+
expected = array.isel(x=[0, 0, 1])
135+
actual = array.groupby("x").map(func)
136+
assert_identical(expected, actual)
137+
138+
139+
def test_ds_groupby_map_change_group_size():
140+
dataset = xr.Dataset({"foo": ("x", [1, 2, 3])}, {"x": [1, 2, 2]})
141+
142+
def func(group):
143+
if group.sizes["x"] == 1:
144+
result = group.isel(x=[0, 0])
145+
else:
146+
result = group.isel(x=[0])
147+
return result
148+
149+
expected = dataset.isel(x=[0, 0, 1])
150+
actual = dataset.groupby("x").map(func)
151+
assert_identical(expected, actual)
152+
153+
110154
def test_da_groupby_map_func_args():
111155
def func(arg1, arg2, arg3=0):
112156
return arg1 + arg2 + arg3

0 commit comments

Comments
 (0)