Skip to content

Commit 7486f4e

Browse files
authored
Bug fixes for DataTree indexing and aggregation (#9626)
* Bug fixes for DataTree indexing and aggregation My implementation of indexing and aggregation was incorrect on child nodes, re-creating the child nodes from the root. There was also another bug when indexing inherited coordinates that meant formerly inherited coordinates were incorrectly dropped from results. * disable broken test
1 parent 56f0e48 commit 7486f4e

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

xarray/core/datatree.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,7 +1681,8 @@ def reduce(
16811681
numeric_only=numeric_only,
16821682
**kwargs,
16831683
)
1684-
result[node.path] = node_result
1684+
path = "/" if node is self else node.relative_to(self)
1685+
result[path] = node_result
16851686
return type(self).from_dict(result, name=self.name)
16861687

16871688
def _selective_indexing(
@@ -1706,15 +1707,17 @@ def _selective_indexing(
17061707
# Ideally, we would avoid creating such coordinates in the first
17071708
# place, but that would require implementing indexing operations at
17081709
# the Variable instead of the Dataset level.
1709-
for k in node_indexers:
1710-
if k not in node._node_coord_variables and k in node_result.coords:
1711-
# We remove all inherited coordinates. Coordinates
1712-
# corresponding to an index would be de-duplicated by
1713-
# _deduplicate_inherited_coordinates(), but indexing (e.g.,
1714-
# with a scalar) can also create scalar coordinates, which
1715-
# need to be explicitly removed.
1716-
del node_result.coords[k]
1717-
result[node.path] = node_result
1710+
if node is not self:
1711+
for k in node_indexers:
1712+
if k not in node._node_coord_variables and k in node_result.coords:
1713+
# We remove all inherited coordinates. Coordinates
1714+
# corresponding to an index would be de-duplicated by
1715+
# _deduplicate_inherited_coordinates(), but indexing (e.g.,
1716+
# with a scalar) can also create scalar coordinates, which
1717+
# need to be explicitly removed.
1718+
del node_result.coords[k]
1719+
path = "/" if node is self else node.relative_to(self)
1720+
result[path] = node_result
17181721
return type(self).from_dict(result, name=self.name)
17191722

17201723
def isel(

xarray/tests/test_datatree.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,18 @@ def test_isel_inherited(self):
16511651
assert_equal(actual, expected)
16521652

16531653
actual = tree.isel(x=slice(None))
1654-
assert_equal(actual, tree)
1654+
1655+
# TODO: re-enable after the fix to copy() from #9628 is submitted
1656+
# actual = tree.children["child"].isel(x=slice(None))
1657+
# expected = tree.children["child"].copy()
1658+
# assert_identical(actual, expected)
1659+
1660+
actual = tree.children["child"].isel(x=0)
1661+
expected = DataTree(
1662+
dataset=xr.Dataset({"foo": 3}, coords={"x": 1}),
1663+
name="child",
1664+
)
1665+
assert_identical(actual, expected)
16551666

16561667
def test_sel(self):
16571668
tree = DataTree.from_dict(
@@ -1667,7 +1678,14 @@ def test_sel(self):
16671678
}
16681679
)
16691680
actual = tree.sel(x=2)
1670-
assert_equal(actual, expected)
1681+
assert_identical(actual, expected)
1682+
1683+
actual = tree.children["first"].sel(x=2)
1684+
expected = DataTree(
1685+
dataset=xr.Dataset({"a": 2}, coords={"x": 2}),
1686+
name="first",
1687+
)
1688+
assert_identical(actual, expected)
16711689

16721690

16731691
class TestAggregations:
@@ -1739,6 +1757,16 @@ def test_dim_argument(self):
17391757
):
17401758
dt.mean("invalid")
17411759

1760+
def test_subtree(self):
1761+
tree = DataTree.from_dict(
1762+
{
1763+
"/child": Dataset({"a": ("x", [1, 2])}),
1764+
}
1765+
)
1766+
expected = DataTree(dataset=Dataset({"a": 1.5}), name="child")
1767+
actual = tree.children["child"].mean()
1768+
assert_identical(expected, actual)
1769+
17421770

17431771
class TestOps:
17441772
def test_unary_op(self):

0 commit comments

Comments
 (0)