Skip to content
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
4 changes: 4 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ Bug Fixes
type error when applying reduction methods, due to the reduction methods being
dynamically generated (:issue:`8136`).
By `Andrew Scherer <https://github.com/andrew-s28>`_.
- :py:meth:`DataArray.get_index` and :py:meth:`Dataset.get_index` now return a
shallow copy of the stored index, so setting ``.name`` on the result no longer
renames the coordinate of the object it came from (:issue:`2949`).
By `Chirag Gupta <https://github.com/chiruu12>`_.

.. _`pandas-dev/pandas#64793`: https://github.com/pandas-dev/pandas/pull/64793

Expand Down
6 changes: 5 additions & 1 deletion xarray/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,11 @@ def get_index(self, key: Hashable) -> pd.Index:
raise KeyError(key)

try:
return self._indexes[key].to_pandas_index()
# Shallow copy so that renaming the returned index, which pandas
# allows in place, cannot reach back into this object's own index.
# It shares the underlying data, and xarray already relies on that
# being free (see IndexVariable._to_index).
return self._indexes[key].to_pandas_index().copy(deep=False)
except KeyError:
return pd.Index(range(self.sizes[key]), name=key)

Expand Down
11 changes: 11 additions & 0 deletions xarray/tests/test_dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,17 @@ def test_get_index(self) -> None:
with pytest.raises(KeyError):
array.get_index("z")

def test_get_index_is_not_a_view_of_the_stored_index(self) -> None:
# GH2949: a pandas index lets its name be set in place, so handing out
# the stored object let a caller rename this array's own coordinate.
array = DataArray(np.zeros(2), coords={"x": ["a", "b"]}, dims=["x"])

array.get_index("x").name = "renamed"
array.to_index().name = "renamed too"
array.to_series().index.name = "and again"

assert array.get_index("x").name == "x"

def test_get_index_size_zero(self) -> None:
array = DataArray(np.zeros((0,)), dims=["x"])
actual = array.get_index("x")
Expand Down
9 changes: 9 additions & 0 deletions xarray/tests/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,15 @@ def test_asarray(self) -> None:
with pytest.raises(TypeError, match=r"cannot directly convert"):
np.asarray(ds)

def test_get_index_is_not_a_view_of_the_stored_index(self) -> None:
# GH2949, the Dataset half: get_index is inherited from
# DataWithCoords, so Dataset handed out the stored index too.
ds = Dataset({"v": ("x", np.zeros(2))}, coords={"x": ["a", "b"]})

ds.get_index("x").name = "renamed"

assert ds.get_index("x").name == "x"

def test_get_index(self) -> None:
ds = Dataset({"foo": (("x", "y"), np.zeros((2, 3)))}, coords={"x": ["a", "b"]})
assert ds.get_index("x").equals(pd.Index(["a", "b"]))
Expand Down
Loading