Skip to content

Coordinates.dims: only include dimensions found in coordinate variables. #10609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions xarray/core/coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from xarray.core.types import DataVars, Self, T_DataArray, T_Xarray
from xarray.core.utils import (
Frozen,
FrozenMappingWarningOnValuesAccess,
ReprObject,
either_dict_or_kwargs,
emit_user_level_warning,
Expand Down Expand Up @@ -111,27 +112,28 @@ def to_dataset(self) -> Dataset:
raise NotImplementedError()

def to_index(self, ordered_dims: Sequence[Hashable] | None = None) -> pd.Index:
"""Convert all index coordinates into a :py:class:`pandas.Index`.
"""Convert all index dimension coordinates into a :py:class:`pandas.Index`.

Parameters
----------
ordered_dims : sequence of hashable, optional
Possibly reordered version of this object's dimensions indicating
Possibly reordered version of this object's dimensions (or the full dimensions
of it's corresponding Dataset, DataArray or DataTree object) indicating
the order in which dimensions should appear on the result.

Returns
-------
pandas.Index
Index subclass corresponding to the outer-product of all dimension
coordinates. This will be a MultiIndex if this object is has more
than more dimension.
than one dimension.
"""
if ordered_dims is None:
ordered_dims = list(self.dims)
elif set(ordered_dims) != set(self.dims):
ordered_dims = list(self._data.dims)
elif set(ordered_dims) != set(self._data.dims):
raise ValueError(
"ordered_dims must match dims, but does not: "
f"{ordered_dims} vs {self.dims}"
f"{ordered_dims} vs {tuple(self._data.dims)}"
)

if len(ordered_dims) == 0:
Expand Down Expand Up @@ -741,8 +743,8 @@ def _names(self) -> set[Hashable]:

@property
def dims(self) -> Frozen[Hashable, int]:
# deliberately display all dims, not just those on coordinate variables - see https://github.com/pydata/xarray/issues/9466
return self._data.dims
dims = calculate_dimensions(self.variables)
return FrozenMappingWarningOnValuesAccess(dims)

@property
def dtypes(self) -> Frozen[Hashable, np.dtype]:
Expand Down Expand Up @@ -851,8 +853,8 @@ def _names(self) -> set[Hashable]:

@property
def dims(self) -> Frozen[Hashable, int]:
# deliberately display all dims, not just those on coordinate variables - see https://github.com/pydata/xarray/issues/9466
return Frozen(self._data.dims)
dims = calculate_dimensions(self.variables)
return FrozenMappingWarningOnValuesAccess(dims)

@property
def dtypes(self) -> Frozen[Hashable, np.dtype]:
Expand Down Expand Up @@ -942,7 +944,8 @@ def __init__(self, dataarray: T_DataArray) -> None:

@property
def dims(self) -> tuple[Hashable, ...]:
return self._data.dims
dims = calculate_dimensions(self._data._coords)
return tuple(dims)

@property
def dtypes(self) -> Frozen[Hashable, np.dtype]:
Expand All @@ -967,7 +970,9 @@ def _update_coords(
self, coords: dict[Hashable, Variable], indexes: dict[Hashable, Index]
) -> None:
validate_dataarray_coords(
self._data.shape, Coordinates._construct_direct(coords, indexes), self.dims
self._data.shape,
Coordinates._construct_direct(coords, indexes),
self._data.dims,
)

self._data._coords = coords
Expand Down
6 changes: 6 additions & 0 deletions xarray/tests/test_dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,12 @@ def test_coords(self) -> None:
self.mda["level_1"] = ("x", np.arange(4))
self.mda.coords["level_1"] = ("x", np.arange(4))

def test_coords_dims(self) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_coords_dims(self) -> None:
# https://github.com/pydata/xarray/issues/9466
def test_coords_dims(self) -> None:

da = DataArray(
[[1.0, 2.0], [3.0, 4.0]], coords={"a": ("x", [0, 1])}, dims=("x", "y")
)
assert da.coords.dims == ("x",)

def test_coords_to_index(self) -> None:
da = DataArray(np.zeros((2, 3)), [("x", [1, 2]), ("y", list("abc"))])

Expand Down
5 changes: 5 additions & 0 deletions xarray/tests/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,11 @@ def test_coords_properties(self) -> None:
"b": np.dtype("int64"),
}

def test_coords_dims(self) -> None:
# https://github.com/pydata/xarray/issues/9466
ds_no_coord = Dataset(data_vars={"a": ("x", [0, 1])})
assert not len(ds_no_coord.coords.dims)

def test_coords_modify(self) -> None:
data = Dataset(
{
Expand Down
12 changes: 12 additions & 0 deletions xarray/tests/test_datatree.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,18 @@ def test_properties(self) -> None:
"b": np.dtype("int64"),
}

def test_dims(self) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably also add a similar test to the one you used for DataArray here too

# https://github.com/pydata/xarray/issues/9466
ds = Dataset(
data_vars={
"foo": (["x", "y"], np.random.randn(2, 3)),
},
)
dt = DataTree(dataset=ds)
dt["child"] = DataTree()

assert not len(dt.coords.dims)

def test_modify(self) -> None:
ds = Dataset(
data_vars={
Expand Down
Loading