Skip to content

DataTree.map_over_datasets behavior can be obscure sometimes #11813

Open

Description

@carlos-rpg

What is your issue?

Consider this code:

import numpy as np
import pandas as pd
import xarray as xr

da = xr.DataArray(
    data=[1., np.nan, 3.],
    coords={"datetime": pd.date_range("2026-10-26", periods=3, freq="D")},
    name="up",
)
dtree = xr.DataTree(dataset=da.to_dataset())
dtree.map_over_datasets(lambda ds: ds.interpolate_na(dim="datetime"))
AttributeError: DatasetView objects are not to be initialized directly.

This will not run because map_over_datasets will iterate over DatasetView objects, even though the documentation says explicitly that the parameter func expects Dataset:

https://docs.xarray.dev/en/latest/generated/xarray.DataTree.map_over_datasets.html

But if you dig in xarray/core/datatree.py and have a look at DatasetView, this is stated in an exception that I didn't encounter:

def __setitem__(self, key, val) -> None:
    raise AttributeError(
        "Mutation of the DatasetView is not allowed, please use `.__setitem__` on the wrapping DataTree node, "
        "or use `dt.to_dataset()` if you want a mutable dataset. If calling this from within `map_over_datasets`,"
        "use `.copy()` first to get a mutable version of the input dataset."
    )

So the solution is to run lambda ds: ds.copy().interpolate_na(dim="datetime"). Not intuitive at all, expecially if one has been using map_over_datasets with other functions without a problem. Shouldn't this be more clear in the documentation?

Activity

  1. added
    needs triageIssue that has not been reviewed by xarray team member
    on Oct 26, 2026
  2. mohamd764 commented on Oct 27, 2026

    @mohamd764

    I hit the same thing on xarray 2026.9.0 (Python 3.13, Linux), and I think it's a bug more than a docs gap. interpolate_na doesn't mutate the input. It goes through _apply_over_vars_with_dim in xarray/core/missing.py, which builds the result with

    ds = type(self)(coords=self.coords, attrs=self.attrs)

    Inside map_over_datasets, type(self) is DatasetView, and its __init__ always raises. Other methods I tried on a view (mean, fillna, differentiate) return a plain Dataset and work fine.

    ffill, bfill, polyfit and curvefit fail the same way. The last two use the same pattern in xarray/computation/fit.py (type(obj)(...)). All of these are still there on main (aee3dc5).

    As a quick check I monkeypatched _apply_over_vars_with_dim to build Dataset(coords=self.coords, attrs=self.attrs) instead, and interpolate_na and ffill then worked inside map_over_datasets. I haven't run the test suite with that change, so it's just a pointer. Until it's fixed, ds.copy() first is the workaround, as you found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs triageIssue that has not been reviewed by xarray team member

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions