Skip to content

Commit 11d0176

Browse files
authored
BUG: name retention in Index.difference corner cases (#38268)
* BUG: name retention in Index.difference corner cases * whatsnew
1 parent eeaf1a1 commit 11d0176

File tree

5 files changed

+28
-10
lines changed

5 files changed

+28
-10
lines changed

doc/source/whatsnew/v1.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,7 @@ Other
825825
- Fixed metadata propagation when selecting columns with ``DataFrame.__getitem__`` (:issue:`28283`)
826826
- Bug in :meth:`Index.intersection` with non-:class:`Index` failing to set the correct name on the returned :class:`Index` (:issue:`38111`)
827827
- Bug in :meth:`RangeIndex.intersection` failing to set the correct name on the returned :class:`Index` in some corner cases (:issue:`38197`)
828+
- Bug in :meth:`Index.difference` failing to set the correct name on the returned :class:`Index` in some corner cases (:issue:`38268`)
828829
- Bug in :meth:`Index.union` behaving differently depending on whether operand is an :class:`Index` or other list-like (:issue:`36384`)
829830
- Bug in :meth:`Index.intersection` with non-matching numeric dtypes casting to ``object`` dtype instead of minimal common dtype (:issue:`38122`)
830831
- Passing an array with 2 or more dimensions to the :class:`Series` constructor now raises the more specific ``ValueError`` rather than a bare ``Exception`` (:issue:`35744`)

pandas/core/indexes/base.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -2913,12 +2913,15 @@ def difference(self, other, sort=None):
29132913
"""
29142914
self._validate_sort_keyword(sort)
29152915
self._assert_can_do_setop(other)
2916+
other, result_name = self._convert_can_do_setop(other)
29162917

29172918
if self.equals(other):
2918-
# pass an empty np.ndarray with the appropriate dtype
2919-
return self._shallow_copy(self._data[:0])
2919+
return self[:0].rename(result_name)
29202920

2921-
other, result_name = self._convert_can_do_setop(other)
2921+
result = self._difference(other, sort=sort)
2922+
return self._wrap_setop_result(other, result)
2923+
2924+
def _difference(self, other, sort):
29222925

29232926
this = self._get_unique_index()
29242927

@@ -2933,7 +2936,7 @@ def difference(self, other, sort=None):
29332936
except TypeError:
29342937
pass
29352938

2936-
return this._shallow_copy(the_diff, name=result_name)
2939+
return the_diff
29372940

29382941
def symmetric_difference(self, other, result_name=None, sort=None):
29392942
"""

pandas/core/indexes/period.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime, timedelta
2-
from typing import Any, cast
2+
from typing import Any
33
import warnings
44

55
import numpy as np
@@ -660,14 +660,14 @@ def _intersection(self, other, sort=False):
660660
def difference(self, other, sort=None):
661661
self._validate_sort_keyword(sort)
662662
self._assert_can_do_setop(other)
663-
other = ensure_index(other)
663+
other, result_name = self._convert_can_do_setop(other)
664664

665665
if self.equals(other):
666-
# pass an empty PeriodArray with the appropriate dtype
666+
return self[:0].rename(result_name)
667+
668+
return self._difference(other, sort=sort)
667669

668-
# TODO: overload DatetimeLikeArrayMixin.__getitem__
669-
values = cast(PeriodArray, self._data[:0])
670-
return type(self)._simple_new(values, name=self.name)
670+
def _difference(self, other, sort):
671671

672672
if is_object_dtype(other):
673673
return self.astype(object).difference(other).astype(self.dtype)

pandas/core/indexes/range.py

+2
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ def _union(self, other, sort):
666666
def difference(self, other, sort=None):
667667
# optimized set operation if we have another RangeIndex
668668
self._validate_sort_keyword(sort)
669+
self._assert_can_do_setop(other)
670+
other, result_name = self._convert_can_do_setop(other)
669671

670672
if not isinstance(other, RangeIndex):
671673
return super().difference(other, sort=sort)

pandas/tests/indexes/test_setops.py

+12
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,18 @@ def test_difference_preserves_type_empty(self, index, sort):
424424
expected = index[:0]
425425
tm.assert_index_equal(result, expected, exact=True)
426426

427+
def test_difference_name_retention_equals(self, index, sort, names):
428+
if isinstance(index, MultiIndex):
429+
names = [[x] * index.nlevels for x in names]
430+
index = index.rename(names[0])
431+
other = index.rename(names[1])
432+
433+
assert index.equals(other)
434+
435+
result = index.difference(other)
436+
expected = index[:0].rename(names[2])
437+
tm.assert_index_equal(result, expected)
438+
427439
def test_intersection_difference_match_empty(self, index, sort):
428440
# GH#20040
429441
# Test that the intersection of an index with an

0 commit comments

Comments
 (0)