Skip to content

Commit 7dd34ea

Browse files
authored
BUG: RangeIndex.union with sort=None and step<0 (#44085)
1 parent f5c2242 commit 7dd34ea

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ Other
606606
^^^^^
607607
- Bug in :meth:`CustomBusinessMonthBegin.__add__` (:meth:`CustomBusinessMonthEnd.__add__`) not applying the extra ``offset`` parameter when beginning (end) of the target month is already a business day (:issue:`41356`)
608608
- Bug in :meth:`RangeIndex.union` with another ``RangeIndex`` with matching (even) ``step`` and starts differing by strictly less than ``step / 2`` (:issue:`44019`)
609+
- Bug in :meth:`RangeIndex.difference` with ``sort=None`` and ``step<0`` failing to sort (:issue:`44085`)
609610

610611
.. ***DO NOT USE THIS SECTION***
611612

pandas/core/indexes/range.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,10 @@ def _difference(self, other, sort=None):
680680
overlap = overlap[::-1]
681681

682682
if len(overlap) == 0:
683-
return self.rename(name=res_name)
683+
result = self.rename(name=res_name)
684+
if sort is None and self.step < 0:
685+
result = result[::-1]
686+
return result
684687
if len(overlap) == len(self):
685688
return self[:0].rename(res_name)
686689
if not isinstance(overlap, RangeIndex):
@@ -704,6 +707,9 @@ def _difference(self, other, sort=None):
704707
new_index = type(self)._simple_new(new_rng, name=res_name)
705708
if first is not self._range:
706709
new_index = new_index[::-1]
710+
711+
if sort is None and new_index.step < 0:
712+
new_index = new_index[::-1]
707713
return new_index
708714

709715
def symmetric_difference(self, other, result_name: Hashable = None, sort=None):

pandas/tests/indexes/ranges/test_setops.py

+28
Original file line numberDiff line numberDiff line change
@@ -317,16 +317,44 @@ def test_difference(self):
317317
result = obj.difference(obj[-3:])
318318
tm.assert_index_equal(result, obj[:-3], exact=True)
319319

320+
# Flipping the step of 'other' doesn't affect the result, but
321+
# flipping the stepof 'self' does when sort=None
320322
result = obj[::-1].difference(obj[-3:])
323+
tm.assert_index_equal(result, obj[:-3], exact=True)
324+
325+
result = obj[::-1].difference(obj[-3:], sort=False)
321326
tm.assert_index_equal(result, obj[:-3][::-1], exact=True)
322327

323328
result = obj[::-1].difference(obj[-3:][::-1])
329+
tm.assert_index_equal(result, obj[:-3], exact=True)
330+
331+
result = obj[::-1].difference(obj[-3:][::-1], sort=False)
324332
tm.assert_index_equal(result, obj[:-3][::-1], exact=True)
325333

326334
result = obj.difference(obj[2:6])
327335
expected = Int64Index([1, 2, 7, 8, 9], name="foo")
328336
tm.assert_index_equal(result, expected)
329337

338+
def test_difference_sort(self):
339+
# GH#44085 ensure we respect the sort keyword
340+
341+
idx = Index(range(4))[::-1]
342+
other = Index(range(3, 4))
343+
344+
result = idx.difference(other)
345+
expected = Index(range(3))
346+
tm.assert_index_equal(result, expected, exact=True)
347+
348+
result = idx.difference(other, sort=False)
349+
expected = expected[::-1]
350+
tm.assert_index_equal(result, expected, exact=True)
351+
352+
# case where the intersection is empty
353+
other = range(10, 12)
354+
result = idx.difference(other, sort=None)
355+
expected = idx[::-1]
356+
tm.assert_index_equal(result, expected, exact=True)
357+
330358
def test_difference_mismatched_step(self):
331359
obj = RangeIndex.from_range(range(1, 10), name="foo")
332360

0 commit comments

Comments
 (0)