Skip to content

Commit f8d9770

Browse files
committed
BUG: Fix metadata mutation in Index set operations (intersection/union) (#63169)
1 parent 7bf6660 commit f8d9770

File tree

2 files changed

+62
-8
lines changed

2 files changed

+62
-8
lines changed

pandas/core/indexes/base.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2975,13 +2975,12 @@ def __bool__(self) -> NoReturn:
29752975
def _get_reconciled_name_object(self, other):
29762976
"""
29772977
If the result of a set operation will be self,
2978-
return self, unless the name changes, in which
2979-
case make a shallow copy of self.
2978+
return a shallow copy of self.
29802979
"""
29812980
name = get_op_result_name(self, other)
29822981
if self.name is not name:
29832982
return self.rename(name)
2984-
return self
2983+
return self.copy()
29852984

29862985
@final
29872986
def _validate_sort_keyword(self, sort) -> None:

pandas/tests/indexes/test_setops.py

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def test_intersection(self, index, sort):
727727

728728
# Corner cases
729729
inter = first.intersection(first, sort=sort)
730-
assert inter is first
730+
assert inter is not first
731731

732732
@pytest.mark.parametrize(
733733
"index2_name,keeps_name",
@@ -812,16 +812,16 @@ def test_union_identity(self, index, sort):
812812
first = index[5:20]
813813

814814
union = first.union(first, sort=sort)
815-
# i.e. identity is not preserved when sort is True
816-
assert (union is first) is (not sort)
815+
# GH#63169 - identity is never preserved now
816+
assert union is not first
817817

818818
# This should no longer be the same object, since [] is not consistent,
819819
# both objects will be recast to dtype('O')
820820
union = first.union(Index([], dtype=first.dtype), sort=sort)
821-
assert (union is first) is (not sort)
821+
assert union is not first
822822

823823
union = Index([], dtype=first.dtype).union(first, sort=sort)
824-
assert (union is first) is (not sort)
824+
assert union is not first
825825

826826
@pytest.mark.parametrize("index", ["string"], indirect=True)
827827
@pytest.mark.parametrize("second_name,expected", [(None, None), ("name", "name")])
@@ -984,3 +984,58 @@ def test_union_pyarrow_timestamp(self):
984984
res = left.union(right)
985985
expected = Index(["2020-01-01", "2020-01-02"], dtype=left.dtype)
986986
tm.assert_index_equal(res, expected)
987+
988+
989+
class TestSetOpsMutation:
990+
def test_intersection_mutation_safety(self):
991+
# GH#63169
992+
index1 = Index([0, 1], name="original")
993+
index2 = Index([0, 1], name="original")
994+
995+
result = index1.intersection(index2)
996+
997+
assert result is not index1
998+
assert result is not index2
999+
1000+
tm.assert_index_equal(result, index1)
1001+
assert result.name == "original"
1002+
1003+
index1.name = "changed"
1004+
1005+
assert result.name == "original"
1006+
assert index1.name == "changed"
1007+
1008+
def test_union_mutation_safety(self):
1009+
# GH#63169
1010+
index1 = Index([0, 1], name="original")
1011+
index2 = Index([0, 1], name="original")
1012+
1013+
result = index1.union(index2)
1014+
1015+
assert result is not index1
1016+
assert result is not index2
1017+
1018+
tm.assert_index_equal(result, index1)
1019+
assert result.name == "original"
1020+
1021+
index1.name = "changed"
1022+
1023+
assert result.name == "original"
1024+
assert index1.name == "changed"
1025+
1026+
def test_union_mutation_safety_other(self):
1027+
# GH#63169
1028+
index1 = Index([], name="original")
1029+
index2 = Index([0, 1], name="original")
1030+
1031+
result = index1.union(index2)
1032+
1033+
assert result is not index2
1034+
1035+
tm.assert_index_equal(result, index2)
1036+
assert result.name == "original"
1037+
1038+
index2.name = "changed"
1039+
1040+
assert result.name == "original"
1041+
assert index2.name == "changed"

0 commit comments

Comments
 (0)