Skip to content

Commit 38dd4ad

Browse files
authored
BUG: RangeIndex.difference missed case (pandas-dev#44107)
1 parent af61e04 commit 38dd4ad

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

pandas/core/indexes/range.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -705,13 +705,21 @@ def _difference(self, other, sort=None):
705705
else:
706706
return super()._difference(other, sort=sort)
707707

708+
elif len(overlap) == 2 and overlap[0] == first[0] and overlap[-1] == first[-1]:
709+
# e.g. range(-8, 20, 7) and range(13, -9, -3)
710+
return self[1:-1]
711+
708712
if overlap.step == first.step:
709713
if overlap[0] == first.start:
710714
# The difference is everything after the intersection
711715
new_rng = range(overlap[-1] + first.step, first.stop, first.step)
712716
elif overlap[-1] == first[-1]:
713717
# The difference is everything before the intersection
714718
new_rng = range(first.start, overlap[0], first.step)
719+
elif overlap._range == first[1:-1]:
720+
# e.g. range(4) and range(1, 3)
721+
step = len(first) - 1
722+
new_rng = first[::step]
715723
else:
716724
# The difference is not range-like
717725
# e.g. range(1, 10, 1) and range(3, 7, 1)
@@ -725,16 +733,19 @@ def _difference(self, other, sort=None):
725733
if overlap.step == first.step * 2:
726734
if overlap[0] == first[0] and overlap[-1] in (first[-1], first[-2]):
727735
# e.g. range(1, 10, 1) and range(1, 10, 2)
728-
return self[1::2]
736+
new_rng = first[1::2]
729737

730738
elif overlap[0] == first[1] and overlap[-1] in (first[-1], first[-2]):
731739
# e.g. range(1, 10, 1) and range(2, 10, 2)
732-
return self[::2]
740+
new_rng = first[::2]
733741

734-
# We can get here with e.g. range(20) and range(0, 10, 2)
742+
else:
743+
# We can get here with e.g. range(20) and range(0, 10, 2)
744+
return super()._difference(other, sort=sort)
735745

736-
# e.g. range(10) and range(0, 10, 3)
737-
return super()._difference(other, sort=sort)
746+
else:
747+
# e.g. range(10) and range(0, 10, 3)
748+
return super()._difference(other, sort=sort)
738749

739750
new_index = type(self)._simple_new(new_rng, name=res_name)
740751
if first is not self._range:

pandas/tests/indexes/ranges/test_setops.py

+18
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,24 @@ def test_difference_mismatched_step(self):
377377
result = obj[::-1].difference(obj[1::2], sort=False)
378378
tm.assert_index_equal(result, expected[::-1], exact=True)
379379

380+
def test_difference_interior_overlap_endpoints_preserved(self):
381+
left = RangeIndex(range(4))
382+
right = RangeIndex(range(1, 3))
383+
384+
result = left.difference(right)
385+
expected = RangeIndex(0, 4, 3)
386+
assert expected.tolist() == [0, 3]
387+
tm.assert_index_equal(result, expected, exact=True)
388+
389+
def test_difference_endpoints_overlap_interior_preserved(self):
390+
left = RangeIndex(-8, 20, 7)
391+
right = RangeIndex(13, -9, -3)
392+
393+
result = left.difference(right)
394+
expected = RangeIndex(-1, 13, 7)
395+
assert expected.tolist() == [-1, 6]
396+
tm.assert_index_equal(result, expected, exact=True)
397+
380398
def test_difference_interior_non_preserving(self):
381399
# case with intersection of length 1 but RangeIndex is not preserved
382400
idx = Index(range(10))

0 commit comments

Comments
 (0)