Skip to content

Commit ba83f65

Browse files
authored
Fix bug where indexes were changed inplace (#6938)
1 parent c4e40d9 commit ba83f65

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

doc/whats-new.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Bug fixes
4949
- Make FacetGrid.set_titles send kwargs correctly using `handle.udpate(kwargs)`.
5050
(:issue:`6839`, :pull:`6843`)
5151
By `Oliver Lopez <https://github.com/lopezvoliver>`_.
52+
- Fix bug where index variables would be changed inplace (:issue:`6931`, :pull:`6938`)
53+
By `Michael Niklas <https://github.com/headtr1ck>`_.
5254

5355
Documentation
5456
~~~~~~~~~~~~~

xarray/core/dataset.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3771,6 +3771,7 @@ def swap_dims(
37713771
indexes: dict[Hashable, Index] = {}
37723772
for k, v in self.variables.items():
37733773
dims = tuple(dims_dict.get(dim, dim) for dim in v.dims)
3774+
var: Variable
37743775
if k in result_dims:
37753776
var = v.to_index_variable()
37763777
var.dims = dims

xarray/core/variable.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Iterable,
1515
Literal,
1616
Mapping,
17+
NoReturn,
1718
Sequence,
1819
)
1920

@@ -536,23 +537,23 @@ def values(self):
536537
def values(self, values):
537538
self.data = values
538539

539-
def to_base_variable(self):
540+
def to_base_variable(self) -> Variable:
540541
"""Return this variable as a base xarray.Variable"""
541542
return Variable(
542-
self.dims, self._data, self._attrs, encoding=self._encoding, fastpath=True
543+
self._dims, self._data, self._attrs, encoding=self._encoding, fastpath=True
543544
)
544545

545546
to_variable = utils.alias(to_base_variable, "to_variable")
546547

547-
def to_index_variable(self):
548+
def to_index_variable(self) -> IndexVariable:
548549
"""Return this variable as an xarray.IndexVariable"""
549550
return IndexVariable(
550-
self.dims, self._data, self._attrs, encoding=self._encoding, fastpath=True
551+
self._dims, self._data, self._attrs, encoding=self._encoding, fastpath=True
551552
)
552553

553554
to_coord = utils.alias(to_index_variable, "to_coord")
554555

555-
def to_index(self):
556+
def to_index(self) -> pd.Index:
556557
"""Convert this variable to a pandas.Index"""
557558
return self.to_index_variable().to_index()
558559

@@ -2879,13 +2880,13 @@ def equals(self, other, equiv=None):
28792880
def _data_equals(self, other):
28802881
return self.to_index().equals(other.to_index())
28812882

2882-
def to_index_variable(self):
2883+
def to_index_variable(self) -> IndexVariable:
28832884
"""Return this variable as an xarray.IndexVariable"""
2884-
return self
2885+
return self.copy()
28852886

28862887
to_coord = utils.alias(to_index_variable, "to_coord")
28872888

2888-
def to_index(self):
2889+
def to_index(self) -> pd.Index:
28892890
"""Convert this variable to a pandas.Index"""
28902891
# n.b. creating a new pandas.Index from an old pandas.Index is
28912892
# basically free as pandas.Index objects are immutable
@@ -2904,7 +2905,7 @@ def to_index(self):
29042905
return index
29052906

29062907
@property
2907-
def level_names(self):
2908+
def level_names(self) -> list[str] | None:
29082909
"""Return MultiIndex level names or None if this IndexVariable has no
29092910
MultiIndex.
29102911
"""
@@ -2922,11 +2923,11 @@ def get_level_variable(self, level):
29222923
return type(self)(self.dims, index.get_level_values(level))
29232924

29242925
@property
2925-
def name(self):
2926+
def name(self) -> Hashable:
29262927
return self.dims[0]
29272928

29282929
@name.setter
2929-
def name(self, value):
2930+
def name(self, value) -> NoReturn:
29302931
raise AttributeError("cannot modify name of IndexVariable in-place")
29312932

29322933
def _inplace_binary_op(self, other, f):

xarray/tests/test_variable.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,15 @@ def test_rolling_window_errors(self):
24222422
def test_coarsen_2d(self):
24232423
super().test_coarsen_2d()
24242424

2425+
def test_to_index_variable_copy(self) -> None:
2426+
# to_index_variable should return a copy
2427+
# https://github.com/pydata/xarray/issues/6931
2428+
a = IndexVariable("x", ["a"])
2429+
b = a.to_index_variable()
2430+
assert a is not b
2431+
b.dims = ("y",)
2432+
assert a.dims == ("x",)
2433+
24252434

24262435
class TestAsCompatibleData:
24272436
def test_unchanged_types(self):

0 commit comments

Comments
 (0)