diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index c5a22d8766a96..d17329902f343 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -548,6 +548,7 @@ Styler Other ^^^^^ - 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`) +- Bug in :meth:`RangeIndex.union` with another ``RangeIndex`` with matching (even) ``step`` and starts differing by strictly less than ``step / 2`` (:issue:`44019`) .. ***DO NOT USE THIS SECTION*** diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 90649ad2dcbc1..55628ae014ea0 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -635,10 +635,13 @@ def _union(self, other: Index, sort): return type(self)(start_r, end_r + step_s, step_s) if ( (step_s % 2 == 0) - and (abs(start_s - start_o) <= step_s / 2) - and (abs(end_s - end_o) <= step_s / 2) + and (abs(start_s - start_o) == step_s / 2) + and (abs(end_s - end_o) == step_s / 2) ): + # e.g. range(0, 10, 2) and range(1, 11, 2) + # but not range(0, 20, 4) and range(1, 21, 4) GH#44019 return type(self)(start_r, end_r + step_s / 2, step_s / 2) + elif step_o % step_s == 0: if ( (start_o - start_s) % step_s == 0 diff --git a/pandas/tests/indexes/ranges/test_setops.py b/pandas/tests/indexes/ranges/test_setops.py index e81271d8ee306..07ec70c109f67 100644 --- a/pandas/tests/indexes/ranges/test_setops.py +++ b/pandas/tests/indexes/ranges/test_setops.py @@ -290,6 +290,15 @@ def test_union_sorted(self, unions): tm.assert_index_equal(res2, expected_sorted, exact=True) tm.assert_index_equal(res3, expected_sorted, exact="equiv") + def test_union_same_step_misaligned(self): + # GH#44019 + left = RangeIndex(range(0, 20, 4)) + right = RangeIndex(range(1, 21, 4)) + + result = left.union(right) + expected = Int64Index([0, 1, 4, 5, 8, 9, 12, 13, 16, 17]) + tm.assert_index_equal(result, expected, exact=True) + def test_difference(self): # GH#12034 Cases where we operate against another RangeIndex and may # get back another RangeIndex